diff options
Diffstat (limited to 'tests')
92 files changed, 12983 insertions, 6938 deletions
diff --git a/tests/lib/test_resolver.c b/tests/lib/test_resolver.c index 0b3dccc820..6a582cceaf 100644 --- a/tests/lib/test_resolver.c +++ b/tests/lib/test_resolver.c @@ -63,7 +63,7 @@ DEFUN (test_resolve, "DNS resolver\n" "Name to resolve\n") { - resolver_resolve(&query, AF_UNSPEC, argv[1]->arg, resolver_result); + resolver_resolve(&query, AF_UNSPEC, 0, argv[1]->arg, resolver_result); return CMD_SUCCESS; } diff --git a/tests/topotests/bfd_topo3/r1/bfd-peers.json b/tests/topotests/bfd_topo3/r1/bfd-peers.json index f8a354fc20..3ce8d97f15 100644 --- a/tests/topotests/bfd_topo3/r1/bfd-peers.json +++ b/tests/topotests/bfd_topo3/r1/bfd-peers.json @@ -18,9 +18,8 @@ "remote-receive-interval": 2000, "remote-transmit-interval": 2000, "status": "up", - "transmit-interval": 2000, "uptime": "*", - "vrf": "default" + "transmit-interval": 2000 }, { "detect-multiplier": 3, @@ -41,9 +40,8 @@ "remote-receive-interval": 600, "remote-transmit-interval": 600, "status": "up", - "transmit-interval": 600, "uptime": "*", - "vrf": "default" + "transmit-interval": 600 }, { "detect-multiplier": 3, @@ -64,8 +62,7 @@ "remote-receive-interval": 2000, "remote-transmit-interval": 2000, "status": "up", - "transmit-interval": 2000, "uptime": "*", - "vrf": "default" + "transmit-interval": 2000 } ] diff --git a/tests/topotests/bfd_topo3/r2/bfd-peers.json b/tests/topotests/bfd_topo3/r2/bfd-peers.json index 786d66dbe3..a40f7e46cf 100644 --- a/tests/topotests/bfd_topo3/r2/bfd-peers.json +++ b/tests/topotests/bfd_topo3/r2/bfd-peers.json @@ -18,9 +18,8 @@ "remote-receive-interval": 600, "remote-transmit-interval": 600, "status": "up", - "transmit-interval": 600, "uptime": "*", - "vrf": "default" + "transmit-interval": 600 }, { "detect-multiplier": 3, @@ -41,8 +40,7 @@ "remote-receive-interval": 2000, "remote-transmit-interval": 2000, "status": "up", - "transmit-interval": 2000, "uptime": "*", - "vrf": "default" + "transmit-interval": 2000 } ] diff --git a/tests/topotests/bfd_topo3/r3/bfd-peers.json b/tests/topotests/bfd_topo3/r3/bfd-peers.json index 1f58663a4e..2182b26ed3 100644 --- a/tests/topotests/bfd_topo3/r3/bfd-peers.json +++ b/tests/topotests/bfd_topo3/r3/bfd-peers.json @@ -18,9 +18,8 @@ "remote-receive-interval": 2000, "remote-transmit-interval": 2000, "status": "up", - "transmit-interval": 2000, "uptime": "*", - "vrf": "default" + "transmit-interval": 2000 }, { "detect-multiplier": 3, @@ -41,9 +40,8 @@ "remote-receive-interval": 2000, "remote-transmit-interval": 2000, "status": "up", - "transmit-interval": 2000, "uptime": "*", - "vrf": "default" + "transmit-interval": 2000 }, { "detect-multiplier": 3, @@ -64,8 +62,7 @@ "remote-receive-interval": 2000, "remote-transmit-interval": 2000, "status": "up", - "transmit-interval": 2000, "uptime": "*", - "vrf": "default" + "transmit-interval": 2000 } ] diff --git a/tests/topotests/bfd_topo3/r4/bfd-peers.json b/tests/topotests/bfd_topo3/r4/bfd-peers.json index 5477f39120..2f41f25c58 100644 --- a/tests/topotests/bfd_topo3/r4/bfd-peers.json +++ b/tests/topotests/bfd_topo3/r4/bfd-peers.json @@ -18,9 +18,8 @@ "remote-receive-interval": 2000, "remote-transmit-interval": 2000, "status": "up", - "transmit-interval": 2000, "uptime": "*", - "vrf": "default" + "transmit-interval": 2000 }, { "detect-multiplier": 3, @@ -41,8 +40,7 @@ "remote-receive-interval": 2000, "remote-transmit-interval": 2000, "status": "up", - "transmit-interval": 2000, "uptime": "*", - "vrf": "default" + "transmit-interval": 2000 } ] diff --git a/tests/topotests/bgp_ecmp_topo1/peer1/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer1/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer1/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer1/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer10/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer10/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer10/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer10/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer11/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer11/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer11/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer11/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer12/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer12/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer12/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer12/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer13/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer13/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer13/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer13/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer14/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer14/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer14/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer14/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer15/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer15/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer15/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer15/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer16/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer16/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer16/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer16/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer17/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer17/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer17/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer17/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer18/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer18/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer18/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer18/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer19/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer19/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer19/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer19/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer2/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer2/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer2/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer2/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer20/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer20/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer20/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer20/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer3/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer3/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer3/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer3/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer4/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer4/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer4/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer4/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer5/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer5/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer5/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer5/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer6/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer6/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer6/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer6/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer7/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer7/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer7/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer7/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer8/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer8/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer8/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer8/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/peer9/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer9/exa-send.py index d9ae3d1906..6bef35508f 100755 --- a/tests/topotests/bgp_ecmp_topo1/peer9/exa-send.py +++ b/tests/topotests/bgp_ecmp_topo1/peer9/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_ecmp_topo1/r1/summary.txt b/tests/topotests/bgp_ecmp_topo1/r1/summary.txt index f0929536d3..68de28a35b 100644 --- a/tests/topotests/bgp_ecmp_topo1/r1/summary.txt +++ b/tests/topotests/bgp_ecmp_topo1/r1/summary.txt @@ -2,7 +2,7 @@ "ipv4Unicast":{ "routerId":"10.0.255.1", "as":100, - "vrfName":"Default", + "vrfName":"default", "peerCount":20, "peers":{ "10.0.1.101":{ diff --git a/tests/topotests/bgp_ecmp_topo1/r1/summary20.txt b/tests/topotests/bgp_ecmp_topo1/r1/summary20.txt index 9015f485f8..4895cdbecf 100644 --- a/tests/topotests/bgp_ecmp_topo1/r1/summary20.txt +++ b/tests/topotests/bgp_ecmp_topo1/r1/summary20.txt @@ -1,7 +1,7 @@ { "routerId":"10.0.255.1", "as":100, - "vrfName":"Default", + "vrfName":"default", "peerCount":20, "peers":{ "10.0.1.101":{ diff --git a/tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py b/tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py index 7b9ef0a505..96e4bf6ed3 100644 --- a/tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py +++ b/tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 # # test_bgp_ecmp_topo1.py @@ -140,12 +140,6 @@ def test_bgp_convergence(): with 'json') and compare with `data` contents. """ output = router.vtysh_cmd(cmd, isjson=True) - if "ipv4Unicast" in output: - output["ipv4Unicast"]["vrfName"] = output["ipv4Unicast"]["vrfName"].replace( - "default", "Default" - ) - elif "vrfName" in output: - output["vrfName"] = output["vrfName"].replace("default", "Default") return topotest.json_cmp(output, data) test_func = functools.partial( diff --git a/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py b/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py index 6ea281e6f0..3e2fb2b6e0 100644 --- a/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py +++ b/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py @@ -148,7 +148,7 @@ def setup_module(mod): router.load_config( TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)), - "--vrfwnetns -o vrf0", + "--vrfwnetns", ) else: router.load_config( diff --git a/tests/topotests/bgp_extended_optional_parameters_length/__init__.py b/tests/topotests/bgp_extended_optional_parameters_length/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_extended_optional_parameters_length/__init__.py diff --git a/tests/topotests/bgp_extended_optional_parameters_length/r1/bgpd.conf b/tests/topotests/bgp_extended_optional_parameters_length/r1/bgpd.conf new file mode 100644 index 0000000000..d83013ca99 --- /dev/null +++ b/tests/topotests/bgp_extended_optional_parameters_length/r1/bgpd.conf @@ -0,0 +1,6 @@ +! +router bgp 65001 + no bgp ebgp-requires-policy + neighbor 192.168.1.2 remote-as external + neighbor 192.168.1.2 extended-optional-parameters +! diff --git a/tests/topotests/bgp_extended_optional_parameters_length/r1/zebra.conf b/tests/topotests/bgp_extended_optional_parameters_length/r1/zebra.conf new file mode 100644 index 0000000000..b29940f46a --- /dev/null +++ b/tests/topotests/bgp_extended_optional_parameters_length/r1/zebra.conf @@ -0,0 +1,4 @@ +! +int r1-eth0 + ip address 192.168.1.1/24 +! diff --git a/tests/topotests/bgp_extended_optional_parameters_length/r2/bgpd.conf b/tests/topotests/bgp_extended_optional_parameters_length/r2/bgpd.conf new file mode 100644 index 0000000000..e390d6ed8d --- /dev/null +++ b/tests/topotests/bgp_extended_optional_parameters_length/r2/bgpd.conf @@ -0,0 +1,8 @@ +router bgp 65002 + no bgp ebgp-requires-policy + neighbor 192.168.1.1 remote-as external + neighbor 192.168.1.1 extended-optional-parameters + address-family ipv4 unicast + redistribute connected + exit-address-family +! diff --git a/tests/topotests/bgp_extended_optional_parameters_length/r2/zebra.conf b/tests/topotests/bgp_extended_optional_parameters_length/r2/zebra.conf new file mode 100644 index 0000000000..dc15cf756a --- /dev/null +++ b/tests/topotests/bgp_extended_optional_parameters_length/r2/zebra.conf @@ -0,0 +1,7 @@ +! +int lo + ip address 172.16.16.1/32 +! +int r2-eth0 + ip address 192.168.1.2/24 +! diff --git a/tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py b/tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py new file mode 100644 index 0000000000..e677dc6ff6 --- /dev/null +++ b/tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python + +# Copyright (c) 2021 by +# Donatas Abraitis <donatas.abraitis@gmail.com> +# +# 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 if Extended Optional Parameters Length encoding format works +if forced with a knob. +https://datatracker.ietf.org/doc/html/rfc9072 +""" + +import os +import sys +import json +import pytest +import functools + +pytestmark = pytest.mark.bgpd + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen + +pytestmark = [pytest.mark.bgpd] + + +def setup_module(mod): + topodef = {"s1": ("r1", "r2")} + tgen = Topogen(topodef, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + for i, (rname, router) in enumerate(router_list.items(), 1): + 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() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_bgp_extended_optional_parameters_length(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + router = tgen.gears["r1"] + + def _bgp_converge(router): + output = json.loads(router.vtysh_cmd("show bgp ipv4 unicast summary json")) + expected = { + "peers": { + "192.168.1.2": { + "pfxRcd": 2, + "pfxSnt": 2, + "state": "Established", + "peerState": "OK", + } + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_converge, router) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assert result is None, "Can't converge with extended-optional-parameters" + + def _bgp_extended_optional_parameters_length(router): + output = json.loads(router.vtysh_cmd("show bgp neighbor 192.168.1.2 json")) + expected = {"192.168.1.2": {"extendedOptionalParametersLength": True}} + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_extended_optional_parameters_length, router) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assert result is None, "Can't see Extended Optional Parameters Length to be used" + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-1.py b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-1.py new file mode 100644 index 0000000000..290bf16fea --- /dev/null +++ b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-1.py @@ -0,0 +1,1542 @@ +#!/usr/bin/env python +# +# Copyright (c) 2019 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF") +# in this file. +# +# 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 VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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. +# + +""" +Following tests are covered to test BGP Gracefull Restart functionality. +Basic Common Test steps for all the test case below : +- Create topology (setup module) + Creating 2 routers topology, r1, r2 in IBGP +- Bring up topology +- Verify for bgp to converge +- Configure BGP Garceful Restart on both the routers. + +1. Transition from Peer-level helper to Global Restarting +2. Transition from Peer-level helper to Global inherit helper +3. Transition from Peer-level restarting to Global inherit helper +4. Default GR functional mode is Helper. +5. Verify that the restarting node sets "R" bit while sending the + BGP open messages after the node restart, only if GR is enabled. +6. Verify if restarting node resets R bit in BGP open message + during normal BGP session flaps as well, even when GR restarting + mode is enabled. Here link flap happen due to interface UP/DOWN. +7. Verify if restarting node resets R bit in BGP + open message during normal BGP session flaps when GR is disabled. +8. Verify that restarting nodes set "F" bit while sending + the BGP open messages after it restarts, only when BGP GR is enabled. +9. Verify that only GR helper routers keep the stale + route entries, not any GR disabled router. +10. Verify that GR helper routers keeps all the routes received + from restarting node if both the routers are configured as + GR restarting node. +11. Verify that GR helper routers delete all the routes + received from a node if both the routers are configured as GR + helper node. +12. After BGP neighborship is established and GR capability is exchanged, + transition restarting router to disabled state and vice versa. +13. After BGP neighborship is established and GR capability is exchanged, + transition restarting router to disabled state and vice versa. +14. Verify that restarting nodes reset "F" bit while sending + the BGP open messages after it's restarts, when BGP GR is **NOT** enabled. +15. Verify that only GR helper routers keep the stale + route entries, not any GR disabled router. +16. Transition from Global Restarting to Disable and then Global + Disable to Restarting. +17. Transition from Global Helper to Disable and then Global + Disable to Helper. +18. Transition from Global Restart to Helper and then Global + Helper to Restart, Global Mode : GR Restarting + PerPeer Mode : GR Helper + GR Mode effective : GR Helper +19. Transition from Peer-level helper to Global Restarting, + Global Mode : GR Restarting + PerPeer Mode : GR Restarting + GR Mode effective : GR Restarting +20. Transition from Peer-level restart to Global Restart + Global Mode : GR Restarting + PerPeer Mode : GR Restarting + GR Mode effective : GR Restarting +21. Transition from Peer-level disabled to Global Restart + Global Mode : GR Restarting + PerPeer Mode : GR Disabled + GR Mode effective : GR Disabled +22. Peer-level inherit from Global Restarting + Global Mode : GR Restart + PerPeer Mode : None + GR Mode effective : GR Restart +23. Transition from Peer-level disbale to Global inherit helper + Global Mode : None + PerPeer Mode : GR Disable + GR Mode effective : GR Disable + +These tests have been broken up into 4 sub python scripts because +the totality of this run was fairly significant. +""" + +import os +import sys +import time +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("../")) +sys.path.append(os.path.join("../lib/")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib.topogen import Topogen, get_topogen +from lib.topolog import logger + +# Required to instantiate the topology builder class. + +# Import topoJson from lib, to create topology and initial configuration +from lib.topojson import build_config_from_json +from lib.bgp import ( + clear_bgp, + verify_bgp_rib, + verify_graceful_restart, + create_router_bgp, + verify_r_bit, + verify_f_bit, + verify_bgp_convergence, + verify_bgp_convergence_from_running_config, +) + +from lib.common_config import ( + write_test_header, + reset_config_on_routers, + start_topology, + kill_router_daemons, + start_router_daemons, + verify_rib, + check_address_types, + write_test_footer, + check_router_status, + shutdown_bringup_interface, + step, + get_frr_ipv6_linklocal, + required_linux_kernel_version, +) + +pytestmark = [pytest.mark.bgpd] + + +# Global variables +NEXT_HOP_IP = {"ipv4": "192.168.1.10", "ipv6": "fd00:0:0:1::10"} +NEXT_HOP_IP_1 = {"ipv4": "192.168.0.1", "ipv6": "fd00::1"} +NEXT_HOP_IP_2 = {"ipv4": "192.168.0.2", "ipv6": "fd00::2"} +BGP_CONVERGENCE = False +GR_RESTART_TIMER = 20 +PREFERRED_NEXT_HOP = "link_local" + + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + + global ADDR_TYPES + + # Required linux kernel version for this suite to run. + result = required_linux_kernel_version("4.16") + if result is not True: + pytest.skip("Kernel requirements are not met") + + testsuite_run_time = time.asctime(time.localtime(time.time())) + logger.info("Testsuite start time: {}".format(testsuite_run_time)) + logger.info("=" * 40) + + logger.info("Running setup_module to create topology") + + # This function initiates the topology build with Topogen... + json_file = "{}/bgp_gr_topojson_topo1.json".format(CWD) + tgen = Topogen(json_file, mod.__name__) + global topo + topo = tgen.json_topo + # ... and here it calls Mininet initialization functions. + + # Starting topology, create tmp files which are loaded to routers + # to start deamons and then start routers + start_topology(tgen) + + # Creating configuration from JSON + build_config_from_json(tgen, topo) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Api call verify whether BGP is converged + ADDR_TYPES = check_address_types() + + BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) + assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format( + BGP_CONVERGENCE + ) + + logger.info("Running setup_module() done") + + +def teardown_module(mod): + """ + Teardown the pytest environment + + * `mod`: module name + """ + + logger.info("Running teardown_module to delete topology") + + tgen = get_topogen() + + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + logger.info( + "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) + ) + logger.info("=" * 40) + + +def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer): + """ + This function groups the repetitive function calls into one function. + """ + + result = create_router_bgp(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"][peer]["links"]["r1-link1"][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, dut, neighbor=neighbor) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"][dut]["links"]["r2-link1"][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, peer, neighbor=neighbor) + + result = verify_bgp_convergence_from_running_config(tgen) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + return True + + +def next_hop_per_address_family( + tgen, dut, peer, addr_type, next_hop_dict, preferred_next_hop=PREFERRED_NEXT_HOP +): + """ + This function returns link_local or global next_hop per address-family + """ + + intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"] + if addr_type == "ipv6" and "link_local" in preferred_next_hop: + next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface) + else: + next_hop = next_hop_dict[addr_type] + + return next_hop + + +def BGP_GR_TC_50_p1(request): + """ + Test Objective : Transition from Peer-level helper to Global inherit helper + Global Mode : None + PerPeer Mode : Helper + GR Mode effective : GR Helper + + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + step( + "Configure R1 as GR helper node at per Peer-level for R2" + " and configure R2 as global restarting node." + ) + + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + step("Verify on R2 that R1 advertises GR capabilities as a helper node") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + next_hop = next_hop_per_address_family( + tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step("Kill BGP on R2") + + kill_router_daemons(tgen, "r2", ["bgpd"]) + + step( + "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB" + ) + + for addr_type in ADDR_TYPES: + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + next_hop = next_hop_per_address_family( + tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step("Bring up BGP on R2 and remove Peer-level GR config from R1 ") + + start_router_daemons(tgen, "r2", ["bgpd"]) + + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-helper": False} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-helper": False} + } + } + } + } + }, + } + } + } + } + + result = create_router_bgp(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, "r1", neighbor=neighbor) + + result = verify_bgp_convergence_from_running_config(tgen) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify on R2 that R1 still advertises GR capabilities as a helper node") + + input_dict = { + "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}}, + "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, + } + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} : Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + next_hop = next_hop_per_address_family( + tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} : Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + step("Kill BGP on R2") + + kill_router_daemons(tgen, "r2", ["bgpd"]) + + step( + "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB" + ) + + for addr_type in ADDR_TYPES: + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} : Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + next_hop = next_hop_per_address_family( + tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} : Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + step("Start BGP on R2") + + start_router_daemons(tgen, "r2", ["bgpd"]) + + write_test_footer(tc_name) + + +def test_BGP_GR_TC_51_p1(request): + """ + Test Objective : Transition from Peer-level restarting to Global inherit helper + Global Mode : None + PerPeer Mode : GR Restart + GR Mode effective : GR Restart + + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + step("Configure R1 as GR restarting node at per Peer-level for R2") + + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart": True} + } + } + } + } + }, + } + } + }, + "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + step("Verify on R2 that R1 advertises GR capabilities as a restarting node") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + next_hop = next_hop_per_address_family( + tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_bgp_rib(tgen, addr_type, "r2", input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step("Kill BGP on R1") + + kill_router_daemons(tgen, "r1", ["bgpd"]) + + step( + "Verify that R1 keeps the stale entries in FIB & R2 keeps stale entries in RIB & FIB" + ) + + for addr_type in ADDR_TYPES: + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + next_hop = next_hop_per_address_family( + tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_bgp_rib(tgen, addr_type, "r2", input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step("Bring up BGP on R1 and remove Peer-level GR config") + + start_router_daemons(tgen, "r1", ["bgpd"]) + + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart": False} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart": False} + } + } + } + } + }, + } + } + } + } + + result = create_router_bgp(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, "r1", neighbor=neighbor) + + result = verify_bgp_convergence_from_running_config(tgen) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify on R2 that R1 advertises GR capabilities as a helper node") + + input_dict = { + "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}}, + "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, + } + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} : Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + next_hop = next_hop_per_address_family( + tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} : Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + step("Kill BGPd on R2") + + kill_router_daemons(tgen, "r2", ["bgpd"]) + + step( + "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB" + ) + + for addr_type in ADDR_TYPES: + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} : Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + next_hop = next_hop_per_address_family( + tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} : Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + step("Start BGP on R2") + + start_router_daemons(tgen, "r2", ["bgpd"]) + + write_test_footer(tc_name) + + +def test_BGP_GR_TC_53_p1(request): + """ + Test Objective : Default GR functional mode is Helper. + Global Mode : None + PerPeer Mode : None + GR Mode effective : GR Helper + + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + step("configure R2 as global restarting node") + + input_dict = {"r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}} + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + step( + "Verify on R2 that R1 advertises GR capabilities as a helper node based on inherit" + ) + + input_dict = { + "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}}, + "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, + } + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + next_hop = next_hop_per_address_family( + tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step("Kill BGPd on R2") + + kill_router_daemons(tgen, "r2", ["bgpd"]) + + step( + "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB" + ) + + for addr_type in ADDR_TYPES: + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + next_hop = next_hop_per_address_family( + tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step("Start BGP on R2") + + start_router_daemons(tgen, "r2", ["bgpd"]) + + write_test_footer(tc_name) + + +def test_BGP_GR_TC_4_p0(request): + """ + Test Objective : Verify that the restarting node sets "R" bit while sending the + BGP open messages after the node restart, only if GR is enabled. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Helper Mode] initialized " + ) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart": True} + } + } + } + } + }, + } + } + }, + "r2": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes + dut = "r1" + peer = "r2" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes + protocol = "bgp" + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("[Phase 2] : R2 goes for reload ") + + kill_router_daemons(tgen, "r2", ["bgpd"]) + + logger.info( + "[Phase 3] : R2 is still down, restart time {} sec." + "So time verify the routes are present in BGP RIB and ZEBRA ".format( + GR_RESTART_TIMER + ) + ) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib( + tgen, addr_type, dut, input_topo, next_hop, expected=False + ) + assert result is not True, ( + "Testcase {} : Failed \n " + "r1: routes are still present in BGP RIB\n Error: {}".format( + tc_name, result + ) + ) + logger.info(" Expected behavior: {}".format(result)) + + # Verifying RIB routes + result = verify_rib( + tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False + ) + assert result is not True, ( + "Testcase {} : Failed \n " + "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) + ) + logger.info(" Expected behavior: {}".format(result)) + + logger.info("[Phase 5] : R2 is about to come up now ") + start_router_daemons(tgen, "r2", ["bgpd"]) + + logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2") + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_BGP_GR_TC_5_1_2_p1(request): + """ + Test Objective : Verify if restarting node resets R bit in BGP open message + during normal BGP session flaps as well, even when GR restarting mode is enabled. + Here link flap happen due to interface UP/DOWN. + + """ + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Restart Mode] initialized " + ) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart": True} + } + } + } + } + }, + } + } + }, + "r2": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": {"graceful-restart": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": {"graceful-restart": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes + dut = "r1" + peer = "r2" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes + protocol = "bgp" + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("[Phase 2] : Now flap the link running the BGP session ") + # Shutdown interface + intf = "r2-r1-eth0" + shutdown_bringup_interface(tgen, "r2", intf) + + # Bring up Interface + shutdown_bringup_interface(tgen, "r2", intf, ifaceaction=True) + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2") + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("[Phase 2] : Restart BGPd on router R2. ") + kill_router_daemons(tgen, "r2", ["bgpd"]) + + start_router_daemons(tgen, "r2", ["bgpd"]) + + logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2") + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_BGP_GR_TC_6_1_2_p1(request): + """ + Test Objective : Verify if restarting node resets R bit in BGP + open message during normal BGP session flaps when GR is disabled. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + "[Phase 1] : Test Setup" "[Restart Mode]R1-----R2[Helper Mode] initialized " + ) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart": True} + } + } + } + } + }, + } + } + }, + "r2": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes + dut = "r1" + peer = "r2" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes + protocol = "bgp" + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("[Phase 1] : Changing mode" "[Disable Mode]R1-----R2[Helper Mode]") + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-disable": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-disable": True} + } + } + } + } + }, + } + } + } + } + + result = create_router_bgp(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, "r1", neighbor=neighbor) + + result = verify_bgp_convergence_from_running_config(tgen) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + # Verify GR stats + input_dict = { + "r2": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-disable": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-disable": True} + } + } + } + } + }, + } + } + }, + } + + # here the verify_graceful_restart fro the neighbor would be + # "NotReceived" as the latest GR config is not yet applied. + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("[Phase 2] : Now flap the link running the BGP session ") + # Shutdown interface + intf = "r2-r1-eth0" + shutdown_bringup_interface(tgen, "r2", intf) + + # Bring up Interface + shutdown_bringup_interface(tgen, "r2", intf, ifaceaction=True) + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_r_bit( + tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n " "r2: R-bit is set to True\n Error: {}".format( + tc_name, result + ) + + logger.info("Restart BGPd on R2 ") + kill_router_daemons(tgen, "r2", ["bgpd"]) + + start_router_daemons(tgen, "r2", ["bgpd"]) + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_r_bit( + tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n " "r2: R-bit is set to True\n Error: {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-2.py b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-2.py new file mode 100644 index 0000000000..0647ad5d06 --- /dev/null +++ b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-2.py @@ -0,0 +1,404 @@ +#!/usr/bin/env python +# +# Copyright (c) 2019 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF") +# in this file. +# +# 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 VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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. +# + +""" +Following tests are covered to test BGP Gracefull Restart functionality. +Basic Common Test steps for all the test case below : +- Create topology (setup module) + Creating 2 routers topology, r1, r2 in IBGP +- Bring up topology +- Verify for bgp to converge +- Configure BGP Garceful Restart on both the routers. + +1. Transition from Peer-level helper to Global Restarting +2. Transition from Peer-level helper to Global inherit helper +3. Transition from Peer-level restarting to Global inherit helper +4. Default GR functional mode is Helper. +5. Verify that the restarting node sets "R" bit while sending the + BGP open messages after the node restart, only if GR is enabled. +6. Verify if restarting node resets R bit in BGP open message + during normal BGP session flaps as well, even when GR restarting + mode is enabled. Here link flap happen due to interface UP/DOWN. +7. Verify if restarting node resets R bit in BGP + open message during normal BGP session flaps when GR is disabled. +8. Verify that restarting nodes set "F" bit while sending + the BGP open messages after it restarts, only when BGP GR is enabled. +9. Verify that only GR helper routers keep the stale + route entries, not any GR disabled router. +10. Verify that GR helper routers keeps all the routes received + from restarting node if both the routers are configured as + GR restarting node. +11. Verify that GR helper routers delete all the routes + received from a node if both the routers are configured as GR + helper node. +12. After BGP neighborship is established and GR capability is exchanged, + transition restarting router to disabled state and vice versa. +13. After BGP neighborship is established and GR capability is exchanged, + transition restarting router to disabled state and vice versa. +14. Verify that restarting nodes reset "F" bit while sending + the BGP open messages after it's restarts, when BGP GR is **NOT** enabled. +15. Verify that only GR helper routers keep the stale + route entries, not any GR disabled router. +16. Transition from Global Restarting to Disable and then Global + Disable to Restarting. +17. Transition from Global Helper to Disable and then Global + Disable to Helper. +18. Transition from Global Restart to Helper and then Global + Helper to Restart, Global Mode : GR Restarting + PerPeer Mode : GR Helper + GR Mode effective : GR Helper +19. Transition from Peer-level helper to Global Restarting, + Global Mode : GR Restarting + PerPeer Mode : GR Restarting + GR Mode effective : GR Restarting +20. Transition from Peer-level restart to Global Restart + Global Mode : GR Restarting + PerPeer Mode : GR Restarting + GR Mode effective : GR Restarting +21. Transition from Peer-level disabled to Global Restart + Global Mode : GR Restarting + PerPeer Mode : GR Disabled + GR Mode effective : GR Disabled +22. Peer-level inherit from Global Restarting + Global Mode : GR Restart + PerPeer Mode : None + GR Mode effective : GR Restart +23. Transition from Peer-level disbale to Global inherit helper + Global Mode : None + PerPeer Mode : GR Disable + GR Mode effective : GR Disable + +These tests have been broken up into 4 sub python scripts because +the totality of this run was fairly significant. +""" + +import os +import sys +import time +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("../")) +sys.path.append(os.path.join("../lib/")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib.topogen import Topogen, get_topogen +from lib.topolog import logger + +# Required to instantiate the topology builder class. + +# Import topoJson from lib, to create topology and initial configuration +from lib.topojson import build_config_from_json +from lib.bgp import ( + clear_bgp, + verify_bgp_rib, + verify_graceful_restart, + create_router_bgp, + verify_r_bit, + verify_f_bit, + verify_bgp_convergence, + verify_bgp_convergence_from_running_config, +) + +from lib.common_config import ( + write_test_header, + reset_config_on_routers, + start_topology, + kill_router_daemons, + start_router_daemons, + verify_rib, + check_address_types, + write_test_footer, + check_router_status, + shutdown_bringup_interface, + step, + get_frr_ipv6_linklocal, + required_linux_kernel_version, +) + +pytestmark = [pytest.mark.bgpd] + + +# Global variables +NEXT_HOP_IP = {"ipv4": "192.168.1.10", "ipv6": "fd00:0:0:1::10"} +NEXT_HOP_IP_1 = {"ipv4": "192.168.0.1", "ipv6": "fd00::1"} +NEXT_HOP_IP_2 = {"ipv4": "192.168.0.2", "ipv6": "fd00::2"} +BGP_CONVERGENCE = False +GR_RESTART_TIMER = 20 +PREFERRED_NEXT_HOP = "link_local" + + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + + global ADDR_TYPES + + # Required linux kernel version for this suite to run. + result = required_linux_kernel_version("4.16") + if result is not True: + pytest.skip("Kernel requirements are not met") + + testsuite_run_time = time.asctime(time.localtime(time.time())) + logger.info("Testsuite start time: {}".format(testsuite_run_time)) + logger.info("=" * 40) + + logger.info("Running setup_module to create topology") + + # This function initiates the topology build with Topogen... + json_file = "{}/bgp_gr_topojson_topo1.json".format(CWD) + tgen = Topogen(json_file, mod.__name__) + global topo + topo = tgen.json_topo + # ... and here it calls Mininet initialization functions. + + # Starting topology, create tmp files which are loaded to routers + # to start deamons and then start routers + start_topology(tgen) + + # Creating configuration from JSON + build_config_from_json(tgen, topo) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Api call verify whether BGP is converged + ADDR_TYPES = check_address_types() + + BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) + assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format( + BGP_CONVERGENCE + ) + + logger.info("Running setup_module() done") + + +def teardown_module(mod): + """ + Teardown the pytest environment + + * `mod`: module name + """ + + logger.info("Running teardown_module to delete topology") + + tgen = get_topogen() + + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + logger.info( + "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) + ) + logger.info("=" * 40) + + +def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer): + """ + This function groups the repetitive function calls into one function. + """ + + result = create_router_bgp(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"][peer]["links"]["r1-link1"][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, dut, neighbor=neighbor) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"][dut]["links"]["r2-link1"][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, peer, neighbor=neighbor) + + result = verify_bgp_convergence_from_running_config(tgen) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + return True + + +def next_hop_per_address_family( + tgen, dut, peer, addr_type, next_hop_dict, preferred_next_hop=PREFERRED_NEXT_HOP +): + """ + This function returns link_local or global next_hop per address-family + """ + + intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"] + if addr_type == "ipv6" and "link_local" in preferred_next_hop: + next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface) + else: + next_hop = next_hop_dict[addr_type] + + return next_hop + + +def test_BGP_GR_TC_8_p1(request): + """ + Test Objective : Verify that restarting nodes set "F" bit while sending + the BGP open messages after it restarts, only when BGP GR is enabled. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Restart Mode] initialized " + ) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "graceful-restart": {"preserve-fw-state": True}, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart": True} + } + } + } + } + }, + }, + } + }, + "r2": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": {"graceful-restart": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": {"graceful-restart": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes + dut = "r1" + peer = "r2" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes + protocol = "bgp" + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("[Phase 2] : R1 goes for reload ") + + kill_router_daemons(tgen, "r1", ["bgpd"]) + + logger.info("[Phase 3] : R1 is about to come up now ") + start_router_daemons(tgen, "r1", ["bgpd"]) + + logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r2", peer="r1") + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_f_bit(tgen, topo, addr_type, input_dict, dut="r2", peer="r1") + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-3.py index 56f6e1a3be..0c3ff6451e 100644 --- a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py +++ b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-3.py @@ -85,6 +85,9 @@ Basic Common Test steps for all the test case below : Global Mode : None PerPeer Mode : GR Disable GR Mode effective : GR Disable + +These tests have been broken up into 4 sub python scripts because +the totality of this run was fairly significant. """ import os @@ -519,1165 +522,6 @@ def BGP_GR_TC_50_p1(request): write_test_footer(tc_name) -def test_BGP_GR_TC_51_p1(request): - """ - Test Objective : Transition from Peer-level restarting to Global inherit helper - Global Mode : None - PerPeer Mode : GR Restart - GR Mode effective : GR Restart - - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - step("Configure R1 as GR restarting node at per Peer-level for R2") - - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart": True} - } - } - } - } - }, - } - } - }, - "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - step("Verify on R2 that R1 advertises GR capabilities as a restarting node") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - for addr_type in ADDR_TYPES: - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - for addr_type in ADDR_TYPES: - next_hop = next_hop_per_address_family( - tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_bgp_rib(tgen, addr_type, "r2", input_topo, next_hop) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - step("Kill BGP on R1") - - kill_router_daemons(tgen, "r1", ["bgpd"]) - - step( - "Verify that R1 keeps the stale entries in FIB & R2 keeps stale entries in RIB & FIB" - ) - - for addr_type in ADDR_TYPES: - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - for addr_type in ADDR_TYPES: - next_hop = next_hop_per_address_family( - tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_bgp_rib(tgen, addr_type, "r2", input_topo, next_hop) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - step("Bring up BGP on R1 and remove Peer-level GR config") - - start_router_daemons(tgen, "r1", ["bgpd"]) - - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart": False} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart": False} - } - } - } - } - }, - } - } - } - } - - result = create_router_bgp(tgen, topo, input_dict) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - for addr_type in ADDR_TYPES: - neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0] - clear_bgp(tgen, addr_type, "r1", neighbor=neighbor) - - result = verify_bgp_convergence_from_running_config(tgen) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - step("Verify on R2 that R1 advertises GR capabilities as a helper node") - - input_dict = { - "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}}, - "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, - } - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - for addr_type in ADDR_TYPES: - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} : Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - for addr_type in ADDR_TYPES: - next_hop = next_hop_per_address_family( - tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} : Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - step("Kill BGPd on R2") - - kill_router_daemons(tgen, "r2", ["bgpd"]) - - step( - "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB" - ) - - for addr_type in ADDR_TYPES: - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} : Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - for addr_type in ADDR_TYPES: - next_hop = next_hop_per_address_family( - tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} : Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - step("Start BGP on R2") - - start_router_daemons(tgen, "r2", ["bgpd"]) - - write_test_footer(tc_name) - - -def test_BGP_GR_TC_53_p1(request): - """ - Test Objective : Default GR functional mode is Helper. - Global Mode : None - PerPeer Mode : None - GR Mode effective : GR Helper - - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - step("configure R2 as global restarting node") - - input_dict = {"r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}} - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - step( - "Verify on R2 that R1 advertises GR capabilities as a helper node based on inherit" - ) - - input_dict = { - "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}}, - "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, - } - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - for addr_type in ADDR_TYPES: - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - for addr_type in ADDR_TYPES: - next_hop = next_hop_per_address_family( - tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - step("Kill BGPd on R2") - - kill_router_daemons(tgen, "r2", ["bgpd"]) - - step( - "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB" - ) - - for addr_type in ADDR_TYPES: - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - for addr_type in ADDR_TYPES: - next_hop = next_hop_per_address_family( - tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - step("Start BGP on R2") - - start_router_daemons(tgen, "r2", ["bgpd"]) - - write_test_footer(tc_name) - - -def test_BGP_GR_TC_4_p0(request): - """ - Test Objective : Verify that the restarting node sets "R" bit while sending the - BGP open messages after the node restart, only if GR is enabled. - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Helper Mode] initialized " - ) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart": True} - } - } - } - } - }, - } - } - }, - "r2": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r2-link1": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r2-link1": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes - dut = "r1" - peer = "r2" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes - protocol = "bgp" - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("[Phase 2] : R2 goes for reload ") - - kill_router_daemons(tgen, "r2", ["bgpd"]) - - logger.info( - "[Phase 3] : R2 is still down, restart time {} sec." - "So time verify the routes are present in BGP RIB and ZEBRA ".format( - GR_RESTART_TIMER - ) - ) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib( - tgen, addr_type, dut, input_topo, next_hop, expected=False - ) - assert result is not True, ( - "Testcase {} : Failed \n " - "r1: routes are still present in BGP RIB\n Error: {}".format( - tc_name, result - ) - ) - logger.info(" Expected behavior: {}".format(result)) - - # Verifying RIB routes - result = verify_rib( - tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False - ) - assert result is not True, ( - "Testcase {} : Failed \n " - "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) - ) - logger.info(" Expected behavior: {}".format(result)) - - logger.info("[Phase 5] : R2 is about to come up now ") - start_router_daemons(tgen, "r2", ["bgpd"]) - - logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2") - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - write_test_footer(tc_name) - - -def test_BGP_GR_TC_5_1_2_p1(request): - """ - Test Objective : Verify if restarting node resets R bit in BGP open message - during normal BGP session flaps as well, even when GR restarting mode is enabled. - Here link flap happen due to interface UP/DOWN. - - """ - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Restart Mode] initialized " - ) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart": True} - } - } - } - } - }, - } - } - }, - "r2": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r2-link1": {"graceful-restart": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r2-link1": {"graceful-restart": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes - dut = "r1" - peer = "r2" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes - protocol = "bgp" - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("[Phase 2] : Now flap the link running the BGP session ") - # Shutdown interface - intf = "r2-r1-eth0" - shutdown_bringup_interface(tgen, "r2", intf) - - # Bring up Interface - shutdown_bringup_interface(tgen, "r2", intf, ifaceaction=True) - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2") - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("[Phase 2] : Restart BGPd on router R2. ") - kill_router_daemons(tgen, "r2", ["bgpd"]) - - start_router_daemons(tgen, "r2", ["bgpd"]) - - logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2") - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - write_test_footer(tc_name) - - -def test_BGP_GR_TC_6_1_2_p1(request): - """ - Test Objective : Verify if restarting node resets R bit in BGP - open message during normal BGP session flaps when GR is disabled. - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - "[Phase 1] : Test Setup" "[Restart Mode]R1-----R2[Helper Mode] initialized " - ) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart": True} - } - } - } - } - }, - } - } - }, - "r2": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r2-link1": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r2-link1": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes - dut = "r1" - peer = "r2" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes - protocol = "bgp" - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("[Phase 1] : Changing mode" "[Disable Mode]R1-----R2[Helper Mode]") - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart-disable": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart-disable": True} - } - } - } - } - }, - } - } - } - } - - result = create_router_bgp(tgen, topo, input_dict) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - for addr_type in ADDR_TYPES: - neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0] - clear_bgp(tgen, addr_type, "r1", neighbor=neighbor) - - result = verify_bgp_convergence_from_running_config(tgen) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - # Verify GR stats - input_dict = { - "r2": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r2-link1": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r2-link1": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart-disable": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart-disable": True} - } - } - } - } - }, - } - } - }, - } - - # here the verify_graceful_restart fro the neighbor would be - # "NotReceived" as the latest GR config is not yet applied. - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("[Phase 2] : Now flap the link running the BGP session ") - # Shutdown interface - intf = "r2-r1-eth0" - shutdown_bringup_interface(tgen, "r2", intf) - - # Bring up Interface - shutdown_bringup_interface(tgen, "r2", intf, ifaceaction=True) - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - result = verify_r_bit( - tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False - ) - assert ( - result is not True - ), "Testcase {} : Failed \n " "r2: R-bit is set to True\n Error: {}".format( - tc_name, result - ) - - logger.info("Restart BGPd on R2 ") - kill_router_daemons(tgen, "r2", ["bgpd"]) - - start_router_daemons(tgen, "r2", ["bgpd"]) - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - result = verify_r_bit( - tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False - ) - assert ( - result is not True - ), "Testcase {} : Failed \n " "r2: R-bit is set to True\n Error: {}".format( - tc_name, result - ) - - write_test_footer(tc_name) - - -def test_BGP_GR_TC_8_p1(request): - """ - Test Objective : Verify that restarting nodes set "F" bit while sending - the BGP open messages after it restarts, only when BGP GR is enabled. - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Restart Mode] initialized " - ) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "graceful-restart": {"preserve-fw-state": True}, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart": True} - } - } - } - } - }, - }, - } - }, - "r2": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r2-link1": {"graceful-restart": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r2-link1": {"graceful-restart": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes - dut = "r1" - peer = "r2" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes - protocol = "bgp" - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("[Phase 2] : R1 goes for reload ") - - kill_router_daemons(tgen, "r1", ["bgpd"]) - - logger.info("[Phase 3] : R1 is about to come up now ") - start_router_daemons(tgen, "r1", ["bgpd"]) - - logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r2", peer="r1") - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - result = verify_f_bit(tgen, topo, addr_type, input_dict, dut="r2", peer="r1") - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - write_test_footer(tc_name) - - def test_BGP_GR_TC_19_p1(request): """ Test Objective : Verify that GR helper routers keeps all the routes received @@ -3904,1165 +2748,6 @@ def test_BGP_GR_TC_45_p1(request): write_test_footer(tc_name) -def test_BGP_GR_TC_46_p1(request): - """ - Test Objective : transition from Peer-level helper to Global Restarting - Global Mode : GR Restarting - PerPeer Mode : GR Helper - GR Mode effective : GR Helper - - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - step( - "Configure R1 and R2 as GR restarting node in global" - " and helper in per-Peer-level" - ) - - input_dict = { - "r1": { - "bgp": { - "graceful-restart": { - "graceful-restart": True, - }, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart-helper": True} - } - } - } - } - }, - }, - } - }, - "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - step("Verify on R2 that R1 advertises GR capabilities as a restarting node") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r2", peer="r1" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - for addr_type in ADDR_TYPES: - dut = "r2" - peer = "r1" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - dut = "r1" - peer = "r2" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - step("Kill BGP on R2") - - kill_router_daemons(tgen, "r2", ["bgpd"]) - - step( - "Verify that R1 keeps the stale entries in RIB & FIB and R2 keeps stale entries in FIB using" - ) - - for addr_type in ADDR_TYPES: - dut = "r2" - peer = "r1" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - dut = "r1" - peer = "r2" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - step( - "Bring up BGP on R1 and remove Peer-level GR config" - " from R1 following by a session reset" - ) - - start_router_daemons(tgen, "r2", ["bgpd"]) - - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart-helper": False} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart-helper": False} - } - } - } - } - }, - } - } - } - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - step("Verify on R2 that R1 advertises GR capabilities as a restarting node") - - input_dict = { - "r1": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, - "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, - } - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r2", peer="r1" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - for addr_type in ADDR_TYPES: - dut = "r1" - peer = "r2" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - dut = "r2" - peer = "r1" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - step("Kill BGP on R1") - - kill_router_daemons(tgen, "r1", ["bgpd"]) - - step( - "Verify that R1 keeps the stale entries in FIB command and R2 keeps stale entries in RIB & FIB" - ) - - for addr_type in ADDR_TYPES: - dut = "r1" - peer = "r2" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - dut = "r2" - peer = "r1" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - write_test_footer(tc_name) - - -def test_BGP_GR_TC_47_p1(request): - """ - Test Objective : transition from Peer-level restart to Global Restart - Global Mode : GR Restarting - PerPeer Mode : GR Restarting - GR Mode effective : GR Restarting - - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - step("Configure R1 and R2 as GR restarting node in global and per-Peer-level") - - input_dict = { - "r1": { - "bgp": { - "graceful-restart": { - "graceful-restart": True, - }, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart": True} - } - } - } - } - }, - }, - } - }, - "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - step("Verify on R2 that R1 advertises GR capabilities as a restarting node") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r2", peer="r1" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - for addr_type in ADDR_TYPES: - dut = "r1" - peer = "r2" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - dut = "r2" - peer = "r1" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - step("Kill BGP on R1") - - kill_router_daemons(tgen, "r1", ["bgpd"]) - - step( - "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB" - ) - - for addr_type in ADDR_TYPES: - dut = "r1" - peer = "r2" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - dut = "r2" - peer = "r1" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - step( - "Bring up BGP on R1 and remove Peer-level GR" - " config from R1 following by a session reset" - ) - - start_router_daemons(tgen, "r1", ["bgpd"]) - - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart": False} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart": False} - } - } - } - } - }, - } - } - } - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - step("Verify on R2 that R1 still advertises GR capabilities as a restarting node") - - input_dict = { - "r1": { - "bgp": { - "graceful-restart": { - "graceful-restart": True, - } - } - }, - "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, - } - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r2", peer="r1" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - for addr_type in ADDR_TYPES: - dut = "r1" - peer = "r2" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - dut = "r2" - peer = "r1" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - step("Kill BGP on R1") - - kill_router_daemons(tgen, "r1", ["bgpd"]) - - step( - "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB" - ) - - for addr_type in ADDR_TYPES: - dut = "r1" - peer = "r2" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - dut = "r2" - peer = "r1" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - write_test_footer(tc_name) - - -def test_BGP_GR_TC_48_p1(request): - """ - Test Objective : transition from Peer-level disabled to Global Restart - Global Mode : GR Restarting - PerPeer Mode : GR Disabled - GR Mode effective : GR Disabled - - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - step( - "Configure R1 as GR restarting node in global level and" - " GR Disabled in per-Peer-level" - ) - - input_dict = { - "r1": { - "bgp": { - "graceful-restart": { - "graceful-restart": True, - }, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart-disable": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart-disable": True} - } - } - } - } - }, - }, - } - }, - "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}}, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - step("Verify on R2 that R1 does't advertise any GR capabilities") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r2", peer="r1" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - for addr_type in ADDR_TYPES: - dut = "r1" - peer = "r2" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - dut = "r2" - peer = "r1" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - step("Kill BGP on R1") - - kill_router_daemons(tgen, "r1", ["bgpd"]) - - step("Verify on R2 and R1 that none of the routers keep stale entries") - - for addr_type in ADDR_TYPES: - dut = "r1" - peer = "r2" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_rib( - tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False - ) - assert result is not True, ( - "Testcase {} : Failed \n " - "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) - ) - - dut = "r2" - peer = "r1" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_bgp_rib( - tgen, addr_type, dut, input_topo, next_hop, expected=False - ) - assert result is not True, ( - "Testcase {} : Failed \n " - "r2: routes are still present in BGP RIB\n Error: {}".format( - tc_name, result - ) - ) - result = verify_rib( - tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False - ) - assert result is not True, ( - "Testcase {} : Failed \n " - "r2: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) - ) - - step("Bring up BGP on R1 and remove Peer-level GR config from R1") - - start_router_daemons(tgen, "r1", ["bgpd"]) - - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart-disable": False} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart-disable": False} - } - } - } - } - }, - } - } - } - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - step("Verify on R2 that R1 advertises GR capabilities as a restarting node") - - input_dict = { - "r1": { - "bgp": { - "graceful-restart": { - "graceful-restart": True, - } - } - }, - "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}}, - } - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r2", peer="r1" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - for addr_type in ADDR_TYPES: - dut = "r1" - peer = "r2" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - dut = "r2" - peer = "r1" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - step("Kill BGP on R1") - - kill_router_daemons(tgen, "r1", ["bgpd"]) - - step( - "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB" - ) - - for addr_type in ADDR_TYPES: - dut = "r1" - peer = "r2" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - dut = "r2" - peer = "r1" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - write_test_footer(tc_name) - - -def test_BGP_GR_TC_49_p1(request): - """ - Test Objective : Peer-level inherit from Global Restarting - Global Mode : GR Restart - PerPeer Mode : None - GR Mode effective : GR Restart - - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - step("Configure R1 as GR restarting node in global level") - - input_dict = { - "r1": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, - "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}}, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - step( - "Verify that R2 receives GR restarting capabilities" - " from R1 based on inheritence" - ) - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r2", peer="r1" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - for addr_type in ADDR_TYPES: - dut = "r1" - peer = "r2" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - dut = "r2" - peer = "r1" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - step("Kill BGPd on router R1") - - kill_router_daemons(tgen, "r1", ["bgpd"]) - - step( - "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB" - ) - - for addr_type in ADDR_TYPES: - dut = "r1" - peer = "r2" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - dut = "r2" - peer = "r1" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - write_test_footer(tc_name) - - -def BGP_GR_TC_52_p1(request): - """ - Test Objective : Transition from Peer-level disbale to Global inherit helper - Global Mode : None - PerPeer Mode : GR Disable - GR Mode effective : GR Disable - - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - step( - "Configure R1 as GR disabled node at per Peer-level for R2" - " & R2 as GR restarting node" - ) - - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart-disable": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart-disable": True} - } - } - } - } - }, - } - } - }, - "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - step("Verify on R2 that R1 does't advertise any GR capabilities") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r2", peer="r1" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - for addr_type in ADDR_TYPES: - dut = "r2" - peer = "r1" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - dut = "r1" - peer = "r2" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - step("Kill BGP on R2") - - kill_router_daemons(tgen, "r2", ["bgpd"]) - - step( - "Verify that R2 keeps the stale entries in FIB & R1 doesn't keep RIB & FIB entries." - ) - - for addr_type in ADDR_TYPES: - dut = "r2" - peer = "r1" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - dut = "r1" - peer = "r2" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_bgp_rib( - tgen, addr_type, dut, input_topo, next_hop, expected=False - ) - assert result is not True, ( - "Testcase {} : Failed \n " - "r1: routes are still present in BGP RIB\n Error: {}".format( - tc_name, result - ) - ) - result = verify_rib( - tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False - ) - assert result is not True, ( - "Testcase {} : Failed \n " - "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) - ) - - step("Bring up BGP on R2 and remove Peer-level GR config from R1") - - start_router_daemons(tgen, "r2", ["bgpd"]) - - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart-disable": False} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1-link1": {"graceful-restart-disable": False} - } - } - } - } - }, - } - } - } - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - step( - "Verify on R2 that R1 advertises GR capabilities as a helper node from global inherit" - ) - - input_dict = { - "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}}, - "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, - } - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r2", peer="r1" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - for addr_type in ADDR_TYPES: - dut = "r2" - peer = "r1" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - dut = "r1" - peer = "r2" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - step("Kill BGP on R2") - - kill_router_daemons(tgen, "r2", ["bgpd"]) - - step( - "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB" - ) - - for addr_type in ADDR_TYPES: - dut = "r2" - peer = "r1" - protocol = "bgp" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_1 - ) - input_topo = {"r1": topo["routers"]["r1"]} - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - dut = "r1" - peer = "r2" - next_hop = next_hop_per_address_family( - tgen, dut, peer, addr_type, NEXT_HOP_IP_2 - ) - input_topo = {"r2": topo["routers"]["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) - assert ( - result is True - ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( - tc_name, result - ) - - write_test_footer(tc_name) - - if __name__ == "__main__": args = ["-s"] + sys.argv[1:] sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-4.py b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-4.py new file mode 100644 index 0000000000..791ca37eae --- /dev/null +++ b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-4.py @@ -0,0 +1,1686 @@ +#!/usr/bin/env python +# +# Copyright (c) 2019 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF") +# in this file. +# +# 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 VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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. +# + +""" +Following tests are covered to test BGP Gracefull Restart functionality. +Basic Common Test steps for all the test case below : +- Create topology (setup module) + Creating 2 routers topology, r1, r2 in IBGP +- Bring up topology +- Verify for bgp to converge +- Configure BGP Garceful Restart on both the routers. + +1. Transition from Peer-level helper to Global Restarting +2. Transition from Peer-level helper to Global inherit helper +3. Transition from Peer-level restarting to Global inherit helper +4. Default GR functional mode is Helper. +5. Verify that the restarting node sets "R" bit while sending the + BGP open messages after the node restart, only if GR is enabled. +6. Verify if restarting node resets R bit in BGP open message + during normal BGP session flaps as well, even when GR restarting + mode is enabled. Here link flap happen due to interface UP/DOWN. +7. Verify if restarting node resets R bit in BGP + open message during normal BGP session flaps when GR is disabled. +8. Verify that restarting nodes set "F" bit while sending + the BGP open messages after it restarts, only when BGP GR is enabled. +9. Verify that only GR helper routers keep the stale + route entries, not any GR disabled router. +10. Verify that GR helper routers keeps all the routes received + from restarting node if both the routers are configured as + GR restarting node. +11. Verify that GR helper routers delete all the routes + received from a node if both the routers are configured as GR + helper node. +12. After BGP neighborship is established and GR capability is exchanged, + transition restarting router to disabled state and vice versa. +13. After BGP neighborship is established and GR capability is exchanged, + transition restarting router to disabled state and vice versa. +14. Verify that restarting nodes reset "F" bit while sending + the BGP open messages after it's restarts, when BGP GR is **NOT** enabled. +15. Verify that only GR helper routers keep the stale + route entries, not any GR disabled router. +16. Transition from Global Restarting to Disable and then Global + Disable to Restarting. +17. Transition from Global Helper to Disable and then Global + Disable to Helper. +18. Transition from Global Restart to Helper and then Global + Helper to Restart, Global Mode : GR Restarting + PerPeer Mode : GR Helper + GR Mode effective : GR Helper +19. Transition from Peer-level helper to Global Restarting, + Global Mode : GR Restarting + PerPeer Mode : GR Restarting + GR Mode effective : GR Restarting +20. Transition from Peer-level restart to Global Restart + Global Mode : GR Restarting + PerPeer Mode : GR Restarting + GR Mode effective : GR Restarting +21. Transition from Peer-level disabled to Global Restart + Global Mode : GR Restarting + PerPeer Mode : GR Disabled + GR Mode effective : GR Disabled +22. Peer-level inherit from Global Restarting + Global Mode : GR Restart + PerPeer Mode : None + GR Mode effective : GR Restart +23. Transition from Peer-level disbale to Global inherit helper + Global Mode : None + PerPeer Mode : GR Disable + GR Mode effective : GR Disable + +These tests have been broken up into 4 sub python scripts because +the totality of this run was fairly significant. +""" + +import os +import sys +import time +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("../")) +sys.path.append(os.path.join("../lib/")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib.topogen import Topogen, get_topogen +from lib.topolog import logger + +# Required to instantiate the topology builder class. + +# Import topoJson from lib, to create topology and initial configuration +from lib.topojson import build_config_from_json +from lib.bgp import ( + clear_bgp, + verify_bgp_rib, + verify_graceful_restart, + create_router_bgp, + verify_r_bit, + verify_f_bit, + verify_bgp_convergence, + verify_bgp_convergence_from_running_config, +) + +from lib.common_config import ( + write_test_header, + reset_config_on_routers, + start_topology, + kill_router_daemons, + start_router_daemons, + verify_rib, + check_address_types, + write_test_footer, + check_router_status, + shutdown_bringup_interface, + step, + get_frr_ipv6_linklocal, + required_linux_kernel_version, +) + +pytestmark = [pytest.mark.bgpd] + + +# Global variables +NEXT_HOP_IP = {"ipv4": "192.168.1.10", "ipv6": "fd00:0:0:1::10"} +NEXT_HOP_IP_1 = {"ipv4": "192.168.0.1", "ipv6": "fd00::1"} +NEXT_HOP_IP_2 = {"ipv4": "192.168.0.2", "ipv6": "fd00::2"} +BGP_CONVERGENCE = False +GR_RESTART_TIMER = 20 +PREFERRED_NEXT_HOP = "link_local" + + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + + global ADDR_TYPES + + # Required linux kernel version for this suite to run. + result = required_linux_kernel_version("4.16") + if result is not True: + pytest.skip("Kernel requirements are not met") + + testsuite_run_time = time.asctime(time.localtime(time.time())) + logger.info("Testsuite start time: {}".format(testsuite_run_time)) + logger.info("=" * 40) + + logger.info("Running setup_module to create topology") + + # This function initiates the topology build with Topogen... + json_file = "{}/bgp_gr_topojson_topo1.json".format(CWD) + tgen = Topogen(json_file, mod.__name__) + global topo + topo = tgen.json_topo + # ... and here it calls Mininet initialization functions. + + # Starting topology, create tmp files which are loaded to routers + # to start deamons and then start routers + start_topology(tgen) + + # Creating configuration from JSON + build_config_from_json(tgen, topo) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Api call verify whether BGP is converged + ADDR_TYPES = check_address_types() + + BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) + assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format( + BGP_CONVERGENCE + ) + + logger.info("Running setup_module() done") + + +def teardown_module(mod): + """ + Teardown the pytest environment + + * `mod`: module name + """ + + logger.info("Running teardown_module to delete topology") + + tgen = get_topogen() + + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + logger.info( + "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) + ) + logger.info("=" * 40) + + +def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer): + """ + This function groups the repetitive function calls into one function. + """ + + result = create_router_bgp(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"][peer]["links"]["r1-link1"][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, dut, neighbor=neighbor) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"][dut]["links"]["r2-link1"][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, peer, neighbor=neighbor) + + result = verify_bgp_convergence_from_running_config(tgen) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + return True + + +def next_hop_per_address_family( + tgen, dut, peer, addr_type, next_hop_dict, preferred_next_hop=PREFERRED_NEXT_HOP +): + """ + This function returns link_local or global next_hop per address-family + """ + + intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"] + if addr_type == "ipv6" and "link_local" in preferred_next_hop: + next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface) + else: + next_hop = next_hop_dict[addr_type] + + return next_hop + + +def BGP_GR_TC_50_p1(request): + """ + Test Objective : Transition from Peer-level helper to Global inherit helper + Global Mode : None + PerPeer Mode : Helper + GR Mode effective : GR Helper + + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + step( + "Configure R1 as GR helper node at per Peer-level for R2" + " and configure R2 as global restarting node." + ) + + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + step("Verify on R2 that R1 advertises GR capabilities as a helper node") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + next_hop = next_hop_per_address_family( + tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step("Kill BGP on R2") + + kill_router_daemons(tgen, "r2", ["bgpd"]) + + step( + "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB" + ) + + for addr_type in ADDR_TYPES: + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + next_hop = next_hop_per_address_family( + tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step("Bring up BGP on R2 and remove Peer-level GR config from R1 ") + + start_router_daemons(tgen, "r2", ["bgpd"]) + + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-helper": False} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-helper": False} + } + } + } + } + }, + } + } + } + } + + result = create_router_bgp(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, "r1", neighbor=neighbor) + + result = verify_bgp_convergence_from_running_config(tgen) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify on R2 that R1 still advertises GR capabilities as a helper node") + + input_dict = { + "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}}, + "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, + } + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} : Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + next_hop = next_hop_per_address_family( + tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} : Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + step("Kill BGP on R2") + + kill_router_daemons(tgen, "r2", ["bgpd"]) + + step( + "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB" + ) + + for addr_type in ADDR_TYPES: + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} : Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + next_hop = next_hop_per_address_family( + tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} : Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + step("Start BGP on R2") + + start_router_daemons(tgen, "r2", ["bgpd"]) + + write_test_footer(tc_name) + + +def test_BGP_GR_TC_46_p1(request): + """ + Test Objective : transition from Peer-level helper to Global Restarting + Global Mode : GR Restarting + PerPeer Mode : GR Helper + GR Mode effective : GR Helper + + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + step( + "Configure R1 and R2 as GR restarting node in global" + " and helper in per-Peer-level" + ) + + input_dict = { + "r1": { + "bgp": { + "graceful-restart": { + "graceful-restart": True, + }, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-helper": True} + } + } + } + } + }, + }, + } + }, + "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + step("Verify on R2 that R1 advertises GR capabilities as a restarting node") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r2", peer="r1" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + dut = "r2" + peer = "r1" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + dut = "r1" + peer = "r2" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + step("Kill BGP on R2") + + kill_router_daemons(tgen, "r2", ["bgpd"]) + + step( + "Verify that R1 keeps the stale entries in RIB & FIB and R2 keeps stale entries in FIB using" + ) + + for addr_type in ADDR_TYPES: + dut = "r2" + peer = "r1" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + dut = "r1" + peer = "r2" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + step( + "Bring up BGP on R1 and remove Peer-level GR config" + " from R1 following by a session reset" + ) + + start_router_daemons(tgen, "r2", ["bgpd"]) + + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-helper": False} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-helper": False} + } + } + } + } + }, + } + } + } + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + step("Verify on R2 that R1 advertises GR capabilities as a restarting node") + + input_dict = { + "r1": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, + "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, + } + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r2", peer="r1" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + dut = "r1" + peer = "r2" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + dut = "r2" + peer = "r1" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + step("Kill BGP on R1") + + kill_router_daemons(tgen, "r1", ["bgpd"]) + + step( + "Verify that R1 keeps the stale entries in FIB command and R2 keeps stale entries in RIB & FIB" + ) + + for addr_type in ADDR_TYPES: + dut = "r1" + peer = "r2" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + dut = "r2" + peer = "r1" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_BGP_GR_TC_47_p1(request): + """ + Test Objective : transition from Peer-level restart to Global Restart + Global Mode : GR Restarting + PerPeer Mode : GR Restarting + GR Mode effective : GR Restarting + + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + step("Configure R1 and R2 as GR restarting node in global and per-Peer-level") + + input_dict = { + "r1": { + "bgp": { + "graceful-restart": { + "graceful-restart": True, + }, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart": True} + } + } + } + } + }, + }, + } + }, + "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + step("Verify on R2 that R1 advertises GR capabilities as a restarting node") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r2", peer="r1" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + dut = "r1" + peer = "r2" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + dut = "r2" + peer = "r1" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + step("Kill BGP on R1") + + kill_router_daemons(tgen, "r1", ["bgpd"]) + + step( + "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB" + ) + + for addr_type in ADDR_TYPES: + dut = "r1" + peer = "r2" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + dut = "r2" + peer = "r1" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + step( + "Bring up BGP on R1 and remove Peer-level GR" + " config from R1 following by a session reset" + ) + + start_router_daemons(tgen, "r1", ["bgpd"]) + + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart": False} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart": False} + } + } + } + } + }, + } + } + } + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + step("Verify on R2 that R1 still advertises GR capabilities as a restarting node") + + input_dict = { + "r1": { + "bgp": { + "graceful-restart": { + "graceful-restart": True, + } + } + }, + "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, + } + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r2", peer="r1" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + dut = "r1" + peer = "r2" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + dut = "r2" + peer = "r1" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + step("Kill BGP on R1") + + kill_router_daemons(tgen, "r1", ["bgpd"]) + + step( + "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB" + ) + + for addr_type in ADDR_TYPES: + dut = "r1" + peer = "r2" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + dut = "r2" + peer = "r1" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_BGP_GR_TC_48_p1(request): + """ + Test Objective : transition from Peer-level disabled to Global Restart + Global Mode : GR Restarting + PerPeer Mode : GR Disabled + GR Mode effective : GR Disabled + + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + step( + "Configure R1 as GR restarting node in global level and" + " GR Disabled in per-Peer-level" + ) + + input_dict = { + "r1": { + "bgp": { + "graceful-restart": { + "graceful-restart": True, + }, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-disable": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-disable": True} + } + } + } + } + }, + }, + } + }, + "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}}, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + step("Verify on R2 that R1 does't advertise any GR capabilities") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r2", peer="r1" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + dut = "r1" + peer = "r2" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + dut = "r2" + peer = "r1" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + step("Kill BGP on R1") + + kill_router_daemons(tgen, "r1", ["bgpd"]) + + step("Verify on R2 and R1 that none of the routers keep stale entries") + + for addr_type in ADDR_TYPES: + dut = "r1" + peer = "r2" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_rib( + tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False + ) + assert result is not True, ( + "Testcase {} : Failed \n " + "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) + ) + + dut = "r2" + peer = "r1" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_bgp_rib( + tgen, addr_type, dut, input_topo, next_hop, expected=False + ) + assert result is not True, ( + "Testcase {} : Failed \n " + "r2: routes are still present in BGP RIB\n Error: {}".format( + tc_name, result + ) + ) + result = verify_rib( + tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False + ) + assert result is not True, ( + "Testcase {} : Failed \n " + "r2: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) + ) + + step("Bring up BGP on R1 and remove Peer-level GR config from R1") + + start_router_daemons(tgen, "r1", ["bgpd"]) + + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-disable": False} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-disable": False} + } + } + } + } + }, + } + } + } + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + step("Verify on R2 that R1 advertises GR capabilities as a restarting node") + + input_dict = { + "r1": { + "bgp": { + "graceful-restart": { + "graceful-restart": True, + } + } + }, + "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}}, + } + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r2", peer="r1" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + dut = "r1" + peer = "r2" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + dut = "r2" + peer = "r1" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + step("Kill BGP on R1") + + kill_router_daemons(tgen, "r1", ["bgpd"]) + + step( + "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB" + ) + + for addr_type in ADDR_TYPES: + dut = "r1" + peer = "r2" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + dut = "r2" + peer = "r1" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_BGP_GR_TC_49_p1(request): + """ + Test Objective : Peer-level inherit from Global Restarting + Global Mode : GR Restart + PerPeer Mode : None + GR Mode effective : GR Restart + + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + step("Configure R1 as GR restarting node in global level") + + input_dict = { + "r1": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, + "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}}, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + step( + "Verify that R2 receives GR restarting capabilities" + " from R1 based on inheritence" + ) + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r2", peer="r1" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + dut = "r1" + peer = "r2" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + dut = "r2" + peer = "r1" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + step("Kill BGPd on router R1") + + kill_router_daemons(tgen, "r1", ["bgpd"]) + + step( + "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB" + ) + + for addr_type in ADDR_TYPES: + dut = "r1" + peer = "r2" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + dut = "r2" + peer = "r1" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + write_test_footer(tc_name) + + +def BGP_GR_TC_52_p1(request): + """ + Test Objective : Transition from Peer-level disbale to Global inherit helper + Global Mode : None + PerPeer Mode : GR Disable + GR Mode effective : GR Disable + + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + step( + "Configure R1 as GR disabled node at per Peer-level for R2" + " & R2 as GR restarting node" + ) + + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-disable": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-disable": True} + } + } + } + } + }, + } + } + }, + "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + step("Verify on R2 that R1 does't advertise any GR capabilities") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r2", peer="r1" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + dut = "r2" + peer = "r1" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + dut = "r1" + peer = "r2" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + step("Kill BGP on R2") + + kill_router_daemons(tgen, "r2", ["bgpd"]) + + step( + "Verify that R2 keeps the stale entries in FIB & R1 doesn't keep RIB & FIB entries." + ) + + for addr_type in ADDR_TYPES: + dut = "r2" + peer = "r1" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + dut = "r1" + peer = "r2" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib( + tgen, addr_type, dut, input_topo, next_hop, expected=False + ) + assert result is not True, ( + "Testcase {} : Failed \n " + "r1: routes are still present in BGP RIB\n Error: {}".format( + tc_name, result + ) + ) + result = verify_rib( + tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False + ) + assert result is not True, ( + "Testcase {} : Failed \n " + "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) + ) + + step("Bring up BGP on R2 and remove Peer-level GR config from R1") + + start_router_daemons(tgen, "r2", ["bgpd"]) + + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-disable": False} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"graceful-restart-disable": False} + } + } + } + } + }, + } + } + } + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + step( + "Verify on R2 that R1 advertises GR capabilities as a helper node from global inherit" + ) + + input_dict = { + "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}}, + "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, + } + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r2", peer="r1" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + dut = "r2" + peer = "r1" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + dut = "r1" + peer = "r2" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + step("Kill BGP on R2") + + kill_router_daemons(tgen, "r2", ["bgpd"]) + + step( + "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB" + ) + + for addr_type in ADDR_TYPES: + dut = "r2" + peer = "r1" + protocol = "bgp" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_1 + ) + input_topo = {"r1": topo["routers"]["r1"]} + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + dut = "r1" + peer = "r2" + next_hop = next_hop_per_address_family( + tgen, dut, peer, addr_type, NEXT_HOP_IP_2 + ) + input_topo = {"r2": topo["routers"]["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) + assert ( + result is True + ), "Testcase {} :Failed \n Routes are still present \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-1.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-1.py new file mode 100644 index 0000000000..064fde1633 --- /dev/null +++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-1.py @@ -0,0 +1,1515 @@ +#!/usr/bin/env python +# +# Copyright (c) 2019 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF") +# in this file. +# +# 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 VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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. +# + +""" +Following tests are covered to test BGP Graceful Restart functionality. +Basic Common Test steps for all the test case below : +- Create topology (setup module) + Creating 7 routers topology +- Bring up topology +- Verify for bgp to converge +- Configure BGP Graceful Restart on both the routers. + +TC_1_2: + Verify that EOR message is sent out only after initial convergence + Verify whether EOR message is received from all the peers after restart +TC_3: + Verify the selection deferral timer functionality when EOR is not sent + by the helper router +TC_11: + Verify that selection-deferral timer sets the maximum time to + avoid deadlock during which the best-path +TC_10: + Test Objective : Test GR scenarios on helper router by enabling + Graceful Restart for multiple address families. +TC_15: + Test Objective : Test GR scenarios by enabling Graceful Restart + for multiple address families.. +TC_16: + Test Objective : Verify BGP-GR feature when restarting node + is a transit router for it's iBGP peers. +TC_18: + Test Objective : Verify that GR helper router deletes stale routes + received from restarting node, if GR capability is not present in +TC_19: + Test Objective : Verify that GR routers keeps all the routes + received from restarting node if both the routers are +TC_26: + Test Objective : Test GR scenarios on helper router by enabling + Graceful Restart for multiple address families. +TC_28: + Test Objective : Verify if helper node goes down before restarting + node comes up online, helper node sets the R-bit to avoid dead-lock +TC_29: + Test Objective : Change timers on the fly, and + verify if it takes immediate effect. +TC_33: + Test Objective : Helper router receives same prefixes from two + different routers (GR-restarting and GR-disabled). Keeps the +TC_34_1: + Test Objective : Restarting node doesn't preserve forwarding + state, helper router should not keep the stale entries. +TC_34_2: + Test Objective : Restarting node doesn't preserve the forwarding + state verify the behaviour on helper node, if it still keeps the +TC_32: + Test Objective : Restarting node is connected to multiple helper + nodes, one of them doesn't send EOR to restarting router. Verify +TC_37: + Test Objective : Verify if helper node restarts before sending the + EOR message, restarting node doesn't wait until stale path timer +TC_30: + Test Objective : Restarting node removes stale routes from Zebra + after receiving an EOR from helper router. + +""" + +import os +import sys +import time +import pytest +from time import sleep + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join("../")) +sys.path.append(os.path.join("../lib/")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib.topogen import Topogen, get_topogen +from lib.topolog import logger + +# Required to instantiate the topology builder class. + +# Import topoJson from lib, to create topology and initial configuration +from lib.topojson import build_config_from_json +from lib.bgp import ( + clear_bgp, + verify_bgp_rib, + verify_graceful_restart, + create_router_bgp, + verify_r_bit, + verify_eor, + verify_f_bit, + verify_bgp_convergence, + verify_gr_address_family, + modify_bgp_config_when_bgpd_down, + verify_graceful_restart_timers, + verify_bgp_convergence_from_running_config, +) + +from lib.common_config import ( + write_test_header, + reset_config_on_routers, + start_topology, + kill_router_daemons, + start_router_daemons, + verify_rib, + check_address_types, + write_test_footer, + check_router_status, + step, + get_frr_ipv6_linklocal, + required_linux_kernel_version, +) + +pytestmark = [pytest.mark.bgpd] + + +# Global variables +BGP_CONVERGENCE = False +GR_RESTART_TIMER = 5 +GR_SELECT_DEFER_TIMER = 5 +GR_STALEPATH_TIMER = 5 +PREFERRED_NEXT_HOP = "link_local" +NEXT_HOP_4 = ["192.168.1.1", "192.168.4.2"] +NEXT_HOP_6 = ["fd00:0:0:1::1", "fd00:0:0:4::2"] + + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + + # Required linux kernel version for this suite to run. + result = required_linux_kernel_version("4.16") + if result is not True: + pytest.skip("Kernel requirements are not met") + + global ADDR_TYPES + + testsuite_run_time = time.asctime(time.localtime(time.time())) + logger.info("Testsuite start time: {}".format(testsuite_run_time)) + logger.info("=" * 40) + + logger.info("Running setup_module to create topology") + + # This function initiates the topology build with Topogen... + json_file = "{}/bgp_gr_topojson_topo2.json".format(CWD) + tgen = Topogen(json_file, mod.__name__) + global topo + topo = tgen.json_topo + # ... and here it calls Mininet initialization functions. + + # Starting topology, create tmp files which are loaded to routers + # to start deamons and then start routers + start_topology(tgen) + + # Creating configuration from JSON + build_config_from_json(tgen, topo) + + # Api call verify whether BGP is converged + ADDR_TYPES = check_address_types() + + for addr_type in ADDR_TYPES: + BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) + assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format( + BGP_CONVERGENCE + ) + + logger.info("Running setup_module() done") + + +def teardown_module(mod): + """ + Teardown the pytest environment + + * `mod`: module name + """ + + logger.info("Running teardown_module to delete topology") + + tgen = get_topogen() + + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + logger.info( + "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) + ) + logger.info("=" * 40) + + +def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer): + """ + This function groups the repetitive function calls into one function. + """ + + logger.info("configure_gr_followed_by_clear: dut %s peer %s", dut, peer) + + result = create_router_bgp(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"][peer]["links"][dut][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, dut, neighbor=neighbor) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"][dut]["links"][peer][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, peer, neighbor=neighbor) + + result = verify_bgp_convergence_from_running_config(tgen) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + return True + + +def next_hop_per_address_family(tgen, dut, peer, addr_type, next_hop_dict): + """ + This function returns link_local or global next_hop per address-family + """ + + intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"] + if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP: + next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface) + else: + next_hop = next_hop_dict[addr_type] + + return next_hop + + +def test_BGP_GR_TC_1_2_p0(request): + """ + Verify that EOR message is sent out only after initial convergence + Verify whether EOR message is received from all the peers after restart + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + "Verify EOR Sent and Received : BGP_GR_TC_1_2 >> " + "BGP GR [Helper Mode]R3-----R1[Restart Mode] " + ) + + # Configure graceful-restart + input_dict = { + "r3": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + "r1": { + "bgp": { + "graceful-restart": { + "graceful-restart": True, + "preserve-fw-state": True, + }, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + }, + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r3" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes received from router R3 + dut = "r1" + input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("R1 goes for reload") + kill_router_daemons(tgen, "r1", ["bgpd"]) + + for addr_type in ADDR_TYPES: + # Verifying RIB routes + input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} + # Verifying RIB routes + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("Starting bgpd process") + start_router_daemons(tgen, "r1", ["bgpd"]) + logger.info("R1 is UP Now") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r3" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes received from router R3 + input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying EOR on restarting router + result = verify_eor(tgen, topo, addr_type, input_dict, dut="r3", peer="r1") + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_BGP_GR_TC_3_p0(request): + """ + Verify the selection deferral timer functionality when EOR is not sent + by the helper router + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + " Verify route download to RIB: BGP_GR_TC_3 >> " + "BGP GR [Helper Mode]R1-----R2[Restart Mode] " + ) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "graceful-restart": { + "disable-eor": True, + }, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1": {"graceful-restart-helper": True} + } + } + } + } + }, + }, + } + }, + "r2": { + "bgp": { + "graceful-restart": { + "graceful-restart": True, + "preserve-fw-state": True, + "timer": {"select-defer-time": GR_SELECT_DEFER_TIMER}, + }, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": {"dest_link": {"r2": {"graceful-restart": True}}} + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": {"dest_link": {"r2": {"graceful-restart": True}}} + } + } + }, + }, + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes received from router R1 + dut = "r2" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("R2 goes for reload ") + kill_router_daemons(tgen, "r2", ["bgpd"]) + + logger.info("R2 is about to come up now") + start_router_daemons(tgen, "r2", ["bgpd"]) + logger.info("R2 is UP Now") + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes received from router R1 + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verify EOR on restarting router + result = verify_eor( + tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n " "r2: EOR is set to True\n Error: {}".format( + tc_name, result + ) + + logger.info( + "Waiting for selection deferral timer({} sec)..".format(GR_SELECT_DEFER_TIMER) + ) + sleep(GR_SELECT_DEFER_TIMER) + + for addr_type in ADDR_TYPES: + # Verifying RIB routes + result = verify_rib(tgen, addr_type, "r2", input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_BGP_GR_TC_11_p0(request): + """ + Verify that selection-deferral timer sets the maximum time to + avoid deadlock during which the best-path + selection process is deferred, after a peer session was restarted + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info("Verify EOR Sent after deferral timeout : BGP_GR_TC_11") + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "graceful-restart": { + "graceful-restart": True, + "select-defer-time": GR_SELECT_DEFER_TIMER, + }, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": {"dest_link": {"r1": {"graceful-restart": True}}}, + "r3": {"dest_link": {"r1": {"graceful-restart": True}}}, + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": {"dest_link": {"r1": {"graceful-restart": True}}}, + "r3": {"dest_link": {"r1": {"graceful-restart": True}}}, + } + } + }, + }, + } + }, + "r3": { + "bgp": { + "graceful-restart": {"disable-eor": True}, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + }, + } + }, + } + + result = create_router_bgp(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + clear_bgp(tgen, addr_type, "r1") + clear_bgp(tgen, addr_type, "r3") + + result = verify_bgp_convergence_from_running_config(tgen, topo) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r3" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes received from router R1 + dut = "r1" + input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("R1 goes for reload") + kill_router_daemons(tgen, "r1", ["bgpd"]) + + logger.info("Starting bgpd process") + start_router_daemons(tgen, "r1", ["bgpd"]) + logger.info("R1 is UP Now") + + for addr_type in ADDR_TYPES: + # Verify EOR on restarting router + result = verify_eor( + tgen, topo, addr_type, input_dict, dut="r1", peer="r3", expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format( + tc_name, result + ) + + logger.info( + "Waiting for selection deferral timer({} sec).. ".format( + GR_SELECT_DEFER_TIMER + 2 + ) + ) + sleep(GR_SELECT_DEFER_TIMER + 2) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes received from router R1 + input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying EOR on restarting router + result = verify_eor( + tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n " "r3: EOR is set to True\n Error: {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_BGP_GR_10_p2(request): + """ + Test Objective : Test GR scenarios on helper router by enabling + Graceful Restart for multiple address families. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + step("Test Setup: [Helper Mode]R3-----R1[Restart Mode] initialized") + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1": { + "next_hop_self": True, + "graceful-restart": True, + "activate": "ipv6", + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1": { + "next_hop_self": True, + "graceful-restart": True, + "activate": "ipv4", + } + } + } + } + } + }, + } + } + }, + "r3": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": { + "graceful-restart-helper": True, + "activate": "ipv6", + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": { + "graceful-restart-helper": True, + "activate": "ipv4", + } + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") + + for addr_type in ADDR_TYPES: + step( + "Verifying GR config and operational state for addr_type {}".format( + addr_type + ) + ) + + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r3" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes + dut = "r3" + input_topo = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_topo) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # verify multi address family + result = verify_gr_address_family( + tgen, + topo, + addr_type, + "ipv4Unicast", + dut="r1", + peer="r3", + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # verify multi address family + result = verify_gr_address_family( + tgen, + topo, + addr_type, + "ipv6Unicast", + dut="r1", + peer="r3", + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # verify multi address family + result = verify_gr_address_family( + tgen, + topo, + addr_type, + "ipv4Unicast", + dut="r3", + peer="r1", + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # verify multi address family + result = verify_gr_address_family( + tgen, + topo, + addr_type, + "ipv6Unicast", + dut="r3", + peer="r1", + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step("Killing bgpd on r1") + + # Kill BGPd daemon on R1 + kill_router_daemons(tgen, "r1", ["bgpd"]) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes + input_topo = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_topo) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step("Starting bgpd on r1") + + # Start BGPd daemon on R1 + start_router_daemons(tgen, "r1", ["bgpd"]) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes + input_topo = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_topo) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def BGP_GR_16_p2(request): + """ + Test Objective : Verify BGP-GR feature when restarting node + is a transit router for it's iBGP peers. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] initialized" + ) + + # Configure graceful-restart and timers + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1": { + "graceful-restart": True, + "next_hop_self": True, + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1": { + "graceful-restart": True, + "next_hop_self": True, + } + } + } + } + } + }, + } + } + }, + "r3": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r3" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info( + "[Step 2] : Test Setup " + "[Helper Mode]R3-----R1[Restart Mode]" + "--------R6[Helper Mode] initialized" + ) + + # Configure graceful-restart and timers + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + } + } + }, + "r2": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes + dut = "r3" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes + input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Kill BGPd daemon on R1 + kill_router_daemons(tgen, "r1", ["bgpd"]) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes + input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Start BGPd daemon on R1 + start_router_daemons(tgen, "r1", ["bgpd"]) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes + input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_bgp_convergence_from_running_config(tgen, topo) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_BGP_GR_18_p1(request): + """ + Test Objective : Verify that GR helper router deletes stale routes + received from restarting node, if GR capability is not present in + restarting node's OPEN message. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + "[Step 1] : Test Setup " "[Helper Mode]R6-----R1[Restart Mode] initialized" + ) + + # Configure graceful-restart and timers + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r6": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r6": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + } + } + }, + "r6": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r6": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r6": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r6" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info( + "[Step 2] : Test Setup " + "[Helper Mode]R6-----R1[Restart Mode]" + "--------R2[Helper Mode] initialized" + ) + + # Configure graceful-restart and timers + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + } + } + }, + "r2": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes + dut = "r6" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes + dut = "r2" + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Kill BGPd daemon on R1 + kill_router_daemons(tgen, "r1", ["bgpd"]) + + logger.info("[Step 3] : Configure R1 to prevent sending EOR") + + # Modify graceful-restart config to prevent sending EOR + input_dict_3 = {"r1": {"bgp": {"graceful-restart": {"disable-eor": True}}}} + + result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3) + + # Modify configuration to delete routes + network = {"ipv4": "101.0.20.1/32", "ipv6": "1::1/128"} + for addr_type in ADDR_TYPES: + input_dict_3 = { + "r1": { + "bgp": { + "address_family": { + addr_type: { + "unicast": { + "advertise_networks": [ + { + "network": network[addr_type], + "no_of_network": 5, + "delete": True, + } + ] + } + } + } + } + } + } + + result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Modify graceful-restart config + input_dict_3 = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1": {"graceful-restart-disable": True} + } + }, + "r6": { + "dest_link": { + "r1": {"graceful-restart-disable": True} + } + }, + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1": {"graceful-restart-disable": True} + } + }, + "r6": { + "dest_link": { + "r1": {"graceful-restart-disable": True} + } + }, + } + } + }, + } + } + } + } + + result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result) + + logger.info("[Step 4] : Bring up the BGPd daemon on R1 for 30" " seconds..") + + # Start BGPd daemon on R1 + start_router_daemons(tgen, "r1", ["bgpd"]) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes + dut = "r6" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "r6: routes are still present in BGP RIB\n Error: {}".format( + tc_name, result + ) + ) + logger.info(" Expected behavior: {}".format(result)) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "r6: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) + ) + logger.info(" Expected behavior: {}".format(result)) + + # Verifying BGP RIB routes + dut = "r2" + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "r2: routes are still present in BGP RIB\n Error: {}".format( + tc_name, result + ) + ) + logger.info(" Expected behavior: {}".format(result)) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "r6: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) + ) + logger.info(" Expected behavior: {}".format(result)) + + write_test_footer(tc_name) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-2.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-2.py new file mode 100644 index 0000000000..4356c4d591 --- /dev/null +++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-2.py @@ -0,0 +1,1216 @@ +#!/usr/bin/env python +# +# Copyright (c) 2019 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF") +# in this file. +# +# 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 VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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. +# + +""" +Following tests are covered to test BGP Graceful Restart functionality. +Basic Common Test steps for all the test case below : +- Create topology (setup module) + Creating 7 routers topology +- Bring up topology +- Verify for bgp to converge +- Configure BGP Graceful Restart on both the routers. + +TC_1_2: + Verify that EOR message is sent out only after initial convergence + Verify whether EOR message is received from all the peers after restart +TC_3: + Verify the selection deferral timer functionality when EOR is not sent + by the helper router +TC_11: + Verify that selection-deferral timer sets the maximum time to + avoid deadlock during which the best-path +TC_10: + Test Objective : Test GR scenarios on helper router by enabling + Graceful Restart for multiple address families. +TC_15: + Test Objective : Test GR scenarios by enabling Graceful Restart + for multiple address families.. +TC_16: + Test Objective : Verify BGP-GR feature when restarting node + is a transit router for it's iBGP peers. +TC_18: + Test Objective : Verify that GR helper router deletes stale routes + received from restarting node, if GR capability is not present in +TC_19: + Test Objective : Verify that GR routers keeps all the routes + received from restarting node if both the routers are +TC_26: + Test Objective : Test GR scenarios on helper router by enabling + Graceful Restart for multiple address families. +TC_28: + Test Objective : Verify if helper node goes down before restarting + node comes up online, helper node sets the R-bit to avoid dead-lock +TC_29: + Test Objective : Change timers on the fly, and + verify if it takes immediate effect. +TC_33: + Test Objective : Helper router receives same prefixes from two + different routers (GR-restarting and GR-disabled). Keeps the +TC_34_1: + Test Objective : Restarting node doesn't preserve forwarding + state, helper router should not keep the stale entries. +TC_34_2: + Test Objective : Restarting node doesn't preserve the forwarding + state verify the behaviour on helper node, if it still keeps the +TC_32: + Test Objective : Restarting node is connected to multiple helper + nodes, one of them doesn't send EOR to restarting router. Verify +TC_37: + Test Objective : Verify if helper node restarts before sending the + EOR message, restarting node doesn't wait until stale path timer +TC_30: + Test Objective : Restarting node removes stale routes from Zebra + after receiving an EOR from helper router. + +""" + +import os +import sys +import time +import pytest +from time import sleep + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join("../")) +sys.path.append(os.path.join("../lib/")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib.topogen import Topogen, get_topogen +from lib.topolog import logger + +# Required to instantiate the topology builder class. + +# Import topoJson from lib, to create topology and initial configuration +from lib.topojson import build_config_from_json +from lib.bgp import ( + clear_bgp, + verify_bgp_rib, + verify_graceful_restart, + create_router_bgp, + verify_r_bit, + verify_eor, + verify_f_bit, + verify_bgp_convergence, + verify_gr_address_family, + modify_bgp_config_when_bgpd_down, + verify_graceful_restart_timers, + verify_bgp_convergence_from_running_config, +) + +from lib.common_config import ( + write_test_header, + reset_config_on_routers, + start_topology, + kill_router_daemons, + start_router_daemons, + verify_rib, + check_address_types, + write_test_footer, + check_router_status, + step, + get_frr_ipv6_linklocal, + required_linux_kernel_version, +) + +pytestmark = [pytest.mark.bgpd] + + +# Global variables +BGP_CONVERGENCE = False +GR_RESTART_TIMER = 5 +GR_SELECT_DEFER_TIMER = 5 +GR_STALEPATH_TIMER = 5 +PREFERRED_NEXT_HOP = "link_local" +NEXT_HOP_4 = ["192.168.1.1", "192.168.4.2"] +NEXT_HOP_6 = ["fd00:0:0:1::1", "fd00:0:0:4::2"] + + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + + # Required linux kernel version for this suite to run. + result = required_linux_kernel_version("4.16") + if result is not True: + pytest.skip("Kernel requirements are not met") + + global ADDR_TYPES + + testsuite_run_time = time.asctime(time.localtime(time.time())) + logger.info("Testsuite start time: {}".format(testsuite_run_time)) + logger.info("=" * 40) + + logger.info("Running setup_module to create topology") + + # This function initiates the topology build with Topogen... + json_file = "{}/bgp_gr_topojson_topo2.json".format(CWD) + tgen = Topogen(json_file, mod.__name__) + global topo + topo = tgen.json_topo + # ... and here it calls Mininet initialization functions. + + # Starting topology, create tmp files which are loaded to routers + # to start deamons and then start routers + start_topology(tgen) + + # Creating configuration from JSON + build_config_from_json(tgen, topo) + + # Api call verify whether BGP is converged + ADDR_TYPES = check_address_types() + + for addr_type in ADDR_TYPES: + BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) + assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format( + BGP_CONVERGENCE + ) + + logger.info("Running setup_module() done") + + +def teardown_module(mod): + """ + Teardown the pytest environment + + * `mod`: module name + """ + + logger.info("Running teardown_module to delete topology") + + tgen = get_topogen() + + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + logger.info( + "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) + ) + logger.info("=" * 40) + + +def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer): + """ + This function groups the repetitive function calls into one function. + """ + + logger.info("configure_gr_followed_by_clear: dut %s peer %s", dut, peer) + + result = create_router_bgp(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"][peer]["links"][dut][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, dut, neighbor=neighbor) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"][dut]["links"][peer][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, peer, neighbor=neighbor) + + result = verify_bgp_convergence_from_running_config(tgen) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + return True + + +def next_hop_per_address_family(tgen, dut, peer, addr_type, next_hop_dict): + """ + This function returns link_local or global next_hop per address-family + """ + + intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"] + if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP: + next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface) + else: + next_hop = next_hop_dict[addr_type] + + return next_hop + + +def test_BGP_GR_26_p2(request): + """ + Test Objective : Test GR scenarios on helper router by enabling + Graceful Restart for multiple address families. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] initialized" + ) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1": { + "graceful-restart": True, + "next_hop_self": True, + "activate": "ipv6", + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1": { + "graceful-restart": True, + "next_hop_self": True, + "activate": "ipv4", + } + } + } + } + } + }, + } + } + }, + "r3": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": { + "graceful-restart-helper": True, + "activate": "ipv6", + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": { + "graceful-restart-helper": True, + "activate": "ipv4", + } + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r3", peer="r1" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes + dut = "r3" + input_topo = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_topo) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Kill BGPd daemon on R1 + kill_router_daemons(tgen, "r1", ["bgpd"]) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes + input_topo = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_topo) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Start BGPd daemon on R1 + start_router_daemons(tgen, "r1", ["bgpd"]) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes + input_topo = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_topo) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_topo) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # verify multi address family + result = verify_gr_address_family( + tgen, + topo, + addr_type, + "ipv4Unicast", + dut="r1", + peer="r3", + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # verify multi address family + result = verify_gr_address_family( + tgen, + topo, + addr_type, + "ipv6Unicast", + dut="r1", + peer="r3", + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # verify multi address family + result = verify_gr_address_family( + tgen, + topo, + addr_type, + "ipv4Unicast", + dut="r3", + peer="r1", + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # verify multi address family + result = verify_gr_address_family( + tgen, + topo, + addr_type, + "ipv6Unicast", + dut="r3", + peer="r1", + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_BGP_GR_chaos_28_p1(request): + """ + Test Objective : Verify if helper node goes down before restarting + node comes up online, helper node sets the R-bit to avoid dead-lock + till SDT expiry. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + "Test Case: test_BGP_GR_chaos_28 :" + "[Helper Mode]R3-----R1[Restart Mode] initialized" + ) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + } + } + }, + "r3": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r3" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("[Step 1] : Kill BGPd daemon on R1..") + + # Kill BGPd daemon on R1 + kill_router_daemons(tgen, "r1", ["bgpd"]) + + logger.info("[Step 2] : Kill BGPd daemon on R3..") + + # Kill BGPd daemon on R3 + kill_router_daemons(tgen, "r3", ["bgpd"]) + + logger.info("[Step 3] : Start BGPd daemon on R1..") + + # Start BGPd daemon on R1 + start_router_daemons(tgen, "r1", ["bgpd"]) + + logger.info("[Step 4] : Start BGPd daemon on R3..") + + # Start BGPd daemon on R3 + start_router_daemons(tgen, "r3", ["bgpd"]) + + # Verify r_bit + for addr_type in ADDR_TYPES: + result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r3", peer="r1") + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_BGP_GR_chaos_29_p1(request): + """ + Test Objective : Change timers on the fly, and + verify if it takes immediate effect. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + " Test Case : test_BGP_GR_chaos_29" + " BGP GR [Helper Mode]R3-----R1[Restart Mode]" + " and [restart-time 150]R1 initialized" + ) + + # Configure graceful-restart and timers + input_dict = { + "r1": { + "bgp": { + "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER}}, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + }, + } + }, + "r3": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r3" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verify graceful-restart timers + input_dict_2 = { + "r1": { + "bgp": { + "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER + 5}} + } + } + } + + result = create_router_bgp(tgen, topo, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "r1": { + "bgp": { + "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER}} + } + } + } + + result = verify_graceful_restart_timers( + tgen, topo, addr_type, input_dict_2, dut="r3", peer="r1" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes before shutting down BGPd daemon + dut = "r3" + input_dict = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("[Step 2] : Kill BGPd daemon on R1..") + + # Kill BGPd daemon on R1 + kill_router_daemons(tgen, "r1", ["bgpd"]) + + logger.info("[Step 3] : Wait for {} seconds..".format(GR_RESTART_TIMER)) + + # Waiting for GR_RESTART_TIMER + sleep(GR_RESTART_TIMER) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes before shutting down BGPd daemon + input_dict = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "r3: routes are still present in BGP RIB\n Error: {}".format( + tc_name, result + ) + ) + logger.info(" Expected behavior: {}".format(result)) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) + ) + logger.info(" Expected behavior: {}".format(result)) + + logger.info("[Step 4] : Start BGPd daemon on R1..") + + # Start BGPd daemon on R1 + start_router_daemons(tgen, "r1", ["bgpd"]) + + write_test_footer(tc_name) + + +def test_BGP_GR_chaos_33_p1(request): + """ + Test Objective : Helper router receives same prefixes from two + different routers (GR-restarting and GR-disabled). Keeps the + stale entry only for GR-restarting node(next-hop is correct). + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + " Test Case : test_BGP_GR_chaos_33 " + "BGP GR " + "[Restart Mode]R1--R3[Helper Mode]--R4[Disabled Mode]" + ) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + } + } + }, + "r3": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + "r4": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r4": {"graceful-restart-disable": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r4": {"graceful-restart-disable": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r3" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("[Step 2] : Advertise same networks from R1 and R4..") + + # Api call to delete advertised networks + input_dict_2 = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "advertise_networks": [ + { + "network": "200.0.20.1/32", + "no_of_network": 2, + } + ] + } + }, + "ipv6": { + "unicast": { + "advertise_networks": [ + {"network": "2001::1/128", "no_of_network": 2} + ] + } + }, + } + } + }, + "r4": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "advertise_networks": [ + {"network": "200.0.20.1/32", "no_of_network": 2} + ] + } + }, + "ipv6": { + "unicast": { + "advertise_networks": [ + {"network": "2001::1/128", "no_of_network": 2} + ] + } + }, + } + } + }, + } + + result = create_router_bgp(tgen, topo, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + # Verifying RIB routes + dut = "r3" + peer1 = "r1" + peer2 = "r4" + intf1 = topo["routers"][peer1]["links"][dut]["interface"] + intf2 = topo["routers"][peer2]["links"][dut]["interface"] + + if addr_type == "ipv4": + next_hop_4 = NEXT_HOP_4 + result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_4) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + if addr_type == "ipv6": + if "link_local" in PREFERRED_NEXT_HOP: + next_hop1 = get_frr_ipv6_linklocal(tgen, peer1, intf=intf1) + next_hop2 = get_frr_ipv6_linklocal(tgen, peer2, intf=intf2) + + next_hop_6 = [next_hop1, next_hop2] + else: + next_hop_6 = NEXT_HOP_6 + + result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_6) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("[Step 3] : Kill BGPd daemon on R1 and R4..") + + # Kill BGPd daemon on R1 + kill_router_daemons(tgen, "r1", ["bgpd"]) + + # Kill BGPd daemon on R4 + kill_router_daemons(tgen, "r4", ["bgpd"]) + + for addr_type in ADDR_TYPES: + # Verifying RIB routes + next_hop_6 = ["fd00:0:0:1::1"] + if addr_type == "ipv4": + next_hop_4 = NEXT_HOP_4[0] + + result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_4) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + if addr_type == "ipv6": + if "link_local" in PREFERRED_NEXT_HOP: + next_hop_6 = get_frr_ipv6_linklocal(tgen, peer1, intf=intf1) + else: + next_hop_6 = NEXT_HOP_6[0] + + result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_6) + + # Verifying RIB routes + if addr_type == "ipv4": + next_hop_4 = NEXT_HOP_4[1] + result = verify_rib( + tgen, addr_type, dut, input_dict_2, next_hop_4, expected=False + ) + assert result is not True, ( + "Testcase {} : Failed \n " + "r3: routes are still present in BGP RIB\n Error: {}".format( + tc_name, result + ) + ) + logger.info(" Expected behavior: {}".format(result)) + + if addr_type == "ipv6": + if "link_local" in PREFERRED_NEXT_HOP: + next_hop_6 = get_frr_ipv6_linklocal(tgen, peer2, intf=intf2) + else: + next_hop_6 = NEXT_HOP_6[1] + + result = verify_rib( + tgen, addr_type, dut, input_dict_2, next_hop_6, expected=False + ) + assert result is not True, ( + "Testcase {} : Failed \n " + "r3: routes are still present in ZEBRA\n Error: {}".format( + tc_name, result + ) + ) + logger.info(" Expected behavior: {}".format(result)) + + logger.info("[Step 4] : Start BGPd daemon on R1 and R4..") + + # Start BGPd daemon on R1 + start_router_daemons(tgen, "r1", ["bgpd"]) + + # Start BGPd daemon on R4 + start_router_daemons(tgen, "r4", ["bgpd"]) + + write_test_footer(tc_name) + + +def test_BGP_GR_chaos_34_2_p1(request): + """ + Test Objective : Restarting node doesn't preserve the forwarding + state verify the behaviour on helper node, if it still keeps the + stale routes. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + " Test Case : test_BGP_GR_chaos_34 " + "BGP GR " + "[Restart Mode]R1---R3[Helper Mode]" + ) + + logger.info("[Step 1] : Configure restarting" " router R1 to prevent ") + logger.info("[Step 2] : Reset the session" " between R1 and R3..") + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "graceful-restart": {"preserve-fw-state": True, "disable-eor": True}, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + }, + } + }, + "r3": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r3" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verify f-bit before killing BGPd daemon + result = verify_f_bit(tgen, topo, addr_type, input_dict, "r3", "r1") + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes after starting BGPd daemon + dut = "r3" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("[Step 3] : Kill BGPd daemon on R1..") + + # Kill BGPd daemon on R1 + kill_router_daemons(tgen, "r1", ["bgpd"]) + + logger.info("[Step 4] : Withdraw/delete the prefixes " "originated from R1..") + + # Api call to delete advertised networks + network = {"ipv4": "101.0.20.1/32", "ipv6": "1::1/128"} + for addr_type in ADDR_TYPES: + input_dict_2 = { + "r1": { + "bgp": { + "address_family": { + addr_type: { + "unicast": { + "advertise_networks": [ + { + "network": network[addr_type], + "no_of_network": 5, + "delete": True, + } + ] + } + } + } + } + } + } + + result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("[Step 5] : Remove the CLI from R1's config to " "set the F-bit..") + + # Modify graceful-restart config not to set f-bit + # and write to /etc/frr + input_dict_2 = {"r1": {"bgp": {"graceful-restart": {"preserve-fw-state": False}}}} + + result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result) + + logger.info("[Step 6] : Bring up the BGPd daemon on R1 again..") + + # Start BGPd daemon on R1 + start_router_daemons(tgen, "r1", ["bgpd"]) + + for addr_type in ADDR_TYPES: + # Verify f-bit after starting BGPd daemon + result = verify_f_bit( + tgen, topo, addr_type, input_dict, "r3", "r1", expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n " "r3: F-bit is set to True\n Error: {}".format( + tc_name, result + ) + logger.info(" Expected behavior: {}".format(result)) + + # Verifying BGP RIB routes after starting BGPd daemon + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "r3: routes are still present in BGP RIB\n Error: {}".format( + tc_name, result + ) + ) + logger.info(" Expected behavior: {}".format(result)) + + # Verifying RIB routes + result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) + ) + logger.info(" Expected behavior: {}".format(result)) + + write_test_footer(tc_name) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-3.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-3.py new file mode 100644 index 0000000000..86d676dd8b --- /dev/null +++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-3.py @@ -0,0 +1,1367 @@ +#!/usr/bin/env python +# +# Copyright (c) 2019 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF") +# in this file. +# +# 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 VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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. +# + +""" +Following tests are covered to test BGP Graceful Restart functionality. +Basic Common Test steps for all the test case below : +- Create topology (setup module) + Creating 7 routers topology +- Bring up topology +- Verify for bgp to converge +- Configure BGP Graceful Restart on both the routers. + +TC_1_2: + Verify that EOR message is sent out only after initial convergence + Verify whether EOR message is received from all the peers after restart +TC_3: + Verify the selection deferral timer functionality when EOR is not sent + by the helper router +TC_11: + Verify that selection-deferral timer sets the maximum time to + avoid deadlock during which the best-path +TC_10: + Test Objective : Test GR scenarios on helper router by enabling + Graceful Restart for multiple address families. +TC_15: + Test Objective : Test GR scenarios by enabling Graceful Restart + for multiple address families.. +TC_16: + Test Objective : Verify BGP-GR feature when restarting node + is a transit router for it's iBGP peers. +TC_18: + Test Objective : Verify that GR helper router deletes stale routes + received from restarting node, if GR capability is not present in +TC_19: + Test Objective : Verify that GR routers keeps all the routes + received from restarting node if both the routers are +TC_26: + Test Objective : Test GR scenarios on helper router by enabling + Graceful Restart for multiple address families. +TC_28: + Test Objective : Verify if helper node goes down before restarting + node comes up online, helper node sets the R-bit to avoid dead-lock +TC_29: + Test Objective : Change timers on the fly, and + verify if it takes immediate effect. +TC_33: + Test Objective : Helper router receives same prefixes from two + different routers (GR-restarting and GR-disabled). Keeps the +TC_34_1: + Test Objective : Restarting node doesn't preserve forwarding + state, helper router should not keep the stale entries. +TC_34_2: + Test Objective : Restarting node doesn't preserve the forwarding + state verify the behaviour on helper node, if it still keeps the +TC_32: + Test Objective : Restarting node is connected to multiple helper + nodes, one of them doesn't send EOR to restarting router. Verify +TC_37: + Test Objective : Verify if helper node restarts before sending the + EOR message, restarting node doesn't wait until stale path timer +TC_30: + Test Objective : Restarting node removes stale routes from Zebra + after receiving an EOR from helper router. + +""" + +import os +import sys +import time +import pytest +from time import sleep + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join("../")) +sys.path.append(os.path.join("../lib/")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib.topogen import Topogen, get_topogen +from lib.topolog import logger + +# Required to instantiate the topology builder class. + +# Import topoJson from lib, to create topology and initial configuration +from lib.topojson import build_config_from_json +from lib.bgp import ( + clear_bgp, + verify_bgp_rib, + verify_graceful_restart, + create_router_bgp, + verify_r_bit, + verify_eor, + verify_f_bit, + verify_bgp_convergence, + verify_gr_address_family, + modify_bgp_config_when_bgpd_down, + verify_graceful_restart_timers, + verify_bgp_convergence_from_running_config, +) + +from lib.common_config import ( + write_test_header, + reset_config_on_routers, + start_topology, + kill_router_daemons, + start_router_daemons, + verify_rib, + check_address_types, + write_test_footer, + check_router_status, + step, + get_frr_ipv6_linklocal, + required_linux_kernel_version, +) + +pytestmark = [pytest.mark.bgpd] + + +# Global variables +BGP_CONVERGENCE = False +GR_RESTART_TIMER = 5 +GR_SELECT_DEFER_TIMER = 5 +GR_STALEPATH_TIMER = 5 +PREFERRED_NEXT_HOP = "link_local" +NEXT_HOP_4 = ["192.168.1.1", "192.168.4.2"] +NEXT_HOP_6 = ["fd00:0:0:1::1", "fd00:0:0:4::2"] + + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + + # Required linux kernel version for this suite to run. + result = required_linux_kernel_version("4.16") + if result is not True: + pytest.skip("Kernel requirements are not met") + + global ADDR_TYPES + + testsuite_run_time = time.asctime(time.localtime(time.time())) + logger.info("Testsuite start time: {}".format(testsuite_run_time)) + logger.info("=" * 40) + + logger.info("Running setup_module to create topology") + + # This function initiates the topology build with Topogen... + json_file = "{}/bgp_gr_topojson_topo2.json".format(CWD) + tgen = Topogen(json_file, mod.__name__) + global topo + topo = tgen.json_topo + # ... and here it calls Mininet initialization functions. + + # Starting topology, create tmp files which are loaded to routers + # to start deamons and then start routers + start_topology(tgen) + + # Creating configuration from JSON + build_config_from_json(tgen, topo) + + # Api call verify whether BGP is converged + ADDR_TYPES = check_address_types() + + for addr_type in ADDR_TYPES: + BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) + assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format( + BGP_CONVERGENCE + ) + + logger.info("Running setup_module() done") + + +def teardown_module(mod): + """ + Teardown the pytest environment + + * `mod`: module name + """ + + logger.info("Running teardown_module to delete topology") + + tgen = get_topogen() + + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + logger.info( + "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) + ) + logger.info("=" * 40) + + +def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer): + """ + This function groups the repetitive function calls into one function. + """ + + logger.info("configure_gr_followed_by_clear: dut %s peer %s", dut, peer) + + result = create_router_bgp(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"][peer]["links"][dut][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, dut, neighbor=neighbor) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"][dut]["links"][peer][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, peer, neighbor=neighbor) + + result = verify_bgp_convergence_from_running_config(tgen) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + return True + + +def next_hop_per_address_family(tgen, dut, peer, addr_type, next_hop_dict): + """ + This function returns link_local or global next_hop per address-family + """ + + intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"] + if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP: + next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface) + else: + next_hop = next_hop_dict[addr_type] + + return next_hop + + +def test_BGP_GR_chaos_34_1_p1(request): + """ + Test Objective : Restarting node doesn't preserve forwarding + state, helper router should not keep the stale entries. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + " Test Case : test_BGP_GR_chaos_31 " + "BGP GR " + "[Restart Mode]R1---R3[Helper Mode]" + ) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "graceful-restart": { + "preserve-fw-state": True, + "timer": {"restart-time": GR_RESTART_TIMER}, + }, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + }, + } + }, + "r3": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r3" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes after starting BGPd daemon + dut = "r3" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info( + "[Step 1] : Remove the preserve-fw-state command" + " from restarting node R1's config" + ) + + # Configure graceful-restart to set f-bit as False + input_dict_2 = {"r1": {"bgp": {"graceful-restart": {"preserve-fw-state": False}}}} + + result = create_router_bgp(tgen, topo, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + logger.info("[Step 2] : Reset the session between R1 and R3..") + + # Reset sessions + for addr_type in ADDR_TYPES: + clear_bgp(tgen, addr_type, "r1") + + result = verify_bgp_convergence_from_running_config(tgen, topo) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + # Verify f-bit after starting BGPd daemon + result = verify_f_bit( + tgen, topo, addr_type, input_dict_2, "r3", "r1", expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n " "r3: F-bit is set to True\n Error: {}".format( + tc_name, result + ) + logger.info(" Expected behavior: {}".format(result)) + + logger.info("[Step 3] : Kill BGPd daemon on R1..") + + # Kill BGPd daemon on R1 + kill_router_daemons(tgen, "r1", ["bgpd"]) + + # Waiting for GR_RESTART_TIMER + logger.info("Waiting for {} sec..".format(GR_RESTART_TIMER)) + sleep(GR_RESTART_TIMER) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes + input_dict = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "r3: routes are still present in BGP RIB\n Error: {}".format( + tc_name, result + ) + ) + logger.info(" Expected behavior: {}".format(result)) + + # Verifying RIB routes + result = verify_rib(tgen, addr_type, dut, input_dict, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) + ) + logger.info(" Expected behavior: {}".format(result)) + + # Start BGPd daemon on R1 + start_router_daemons(tgen, "r1", ["bgpd"]) + + write_test_footer(tc_name) + + +def test_BGP_GR_chaos_32_p1(request): + """ + Test Objective : Restarting node is connected to multiple helper + nodes, one of them doesn't send EOR to restarting router. Verify + that only after SDT restarting node send EOR to all helper peers + excluding the prefixes originated by faulty router. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + " Test Case : test_BGP_GR_chaos_32 " + "BGP GR " + "[Restart Mode]R1---R3&R5[Helper Mode]" + ) + + logger.info( + "[Step 1] : Change the mode on R1 be a restarting" " node on global level" + ) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "graceful-restart": {"graceful-restart": True}, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"next_hop_self": True}}}, + "r5": {"dest_link": {"r1": {"graceful-restart": True}}}, + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"next_hop_self": True}}}, + "r5": {"dest_link": {"r1": {"graceful-restart": True}}}, + } + } + }, + }, + } + }, + "r5": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r5": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r5": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r5") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r5" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes after starting BGPd daemon + dut = "r3" + input_dict_1 = {key: topo["routers"][key] for key in ["r5"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("[Step 2] : Kill BGPd daemon on R1..") + # Kill BGPd daemon on R1 + kill_router_daemons(tgen, "r1", ["bgpd"]) + + logger.info("[Step 3] : Withdraw all the advertised prefixes from R5") + + # Api call to delete advertised networks + network = {"ipv4": "105.0.20.1/32", "ipv6": "5::1/128"} + for addr_type in ADDR_TYPES: + input_dict_2 = { + "r5": { + "bgp": { + "address_family": { + addr_type: { + "unicast": { + "advertise_networks": [ + { + "network": network[addr_type], + "no_of_network": 5, + "delete": True, + } + ] + } + } + } + } + } + } + + result = create_router_bgp(tgen, topo, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + logger.info( + "[Step 4] : Stop the helper router R5 from sending EOR" " message using CLI" + ) + + # Modify graceful-restart config to prevent sending EOR + input_dict_3 = {"r5": {"bgp": {"graceful-restart": {"disable-eor": True}}}} + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + logger.info("[Step 5] : Bring up the BGPd daemon on R1..") + + # Start BGPd daemon on R1 + start_router_daemons(tgen, "r1", ["bgpd"]) + + for addr_type in ADDR_TYPES: + # Verify EOR is disabled + result = verify_eor( + tgen, topo, addr_type, input_dict_3, dut="r5", peer="r1", expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n " "r5: EOR is set to TRUE\n Error: {}".format( + tc_name, result + ) + logger.info(" Expected behavior: {}".format(result)) + + # Verifying BGP RIB routes after starting BGPd daemon + input_dict_1 = {key: topo["routers"][key] for key in ["r5"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "r3: routes are still present in BGP RIB\n Error: {}".format( + tc_name, result + ) + ) + logger.info(" Expected behavior: {}".format(result)) + + # Verifying RIB routes + result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) + ) + logger.info(" Expected behavior: {}".format(result)) + + write_test_footer(tc_name) + + +def test_BGP_GR_chaos_37_p1(request): + """ + Test Objective : Verify if helper node restarts before sending the + EOR message, restarting node doesn't wait until stale path timer + expiry to do the best path selection and sends an EOR + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + " Test Case : test_BGP_GR_chaos_37 " + "BGP GR " + "[Restart Mode]R1---R3[Helper Mode]" + ) + + logger.info( + "[Step 1] : Configure restarting router R3 to prevent " "sending an EOR.." + ) + + logger.info("[Step 2] : Reset the session between R3 and R1..") + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + } + } + }, + "r3": { + "bgp": { + "graceful-restart": {"disable-eor": True}, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + }, + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r3" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verify EOR is disabled + result = verify_eor( + tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n " "r3: EOR is set to True\n Error: {}".format( + tc_name, result + ) + logger.info(" Expected behavior: {}".format(result)) + + # Verifying BGP RIB routes after starting BGPd daemon + dut = "r1" + input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("[Step 3] : Kill BGPd daemon on R1..") + + # Kill BGPd daemon on R1 + kill_router_daemons(tgen, "r1", ["bgpd"]) + + logger.info("[Step 4] : Start BGPd daemon on R1..") + + # Start BGPd daemon on R1 + start_router_daemons(tgen, "r1", ["bgpd"]) + + logger.info("[Step 5] : Kill BGPd daemon on R3..") + + # Kill BGPd daemon on R3 + kill_router_daemons(tgen, "r3", ["bgpd"]) + + # Modify graceful-restart config to prevent sending EOR + input_dict_2 = {"r3": {"bgp": {"graceful-restart": {"disable-eor": True}}}} + + result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result) + + logger.info("[Step 6] : Start BGPd daemon on R3..") + + # Start BGPd daemon on R3 + start_router_daemons(tgen, "r3", ["bgpd"]) + + for addr_type in ADDR_TYPES: + # Verify r_bit + result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r3") + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes + input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verify EOR is send from R1 to R3 + input_dict_3 = {"r1": {"bgp": {"graceful-restart": {"disable-eor": True}}}} + + result = verify_eor( + tgen, topo, addr_type, input_dict_3, dut="r1", peer="r3", expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_BGP_GR_chaos_30_p1(request): + """ + Test Objective : Restarting node removes stale routes from Zebra + after receiving an EOR from helper router. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + " Test Case : test_BGP_GR_chaos_30 " + "BGP GR [Helper Mode]R3-----R1[Restart Mode] " + ) + + # Configure graceful-restart and timers + input_dict = { + "r1": { + "bgp": { + "graceful-restart": {"preserve-fw-state": True}, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + }, + } + }, + "r3": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r3" + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes before shutting down BGPd daemon + dut = "r1" + input_dict = {key: topo["routers"][key] for key in ["r3"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + logger.info("[Step 2] : Kill BGPd daemon on R1..") + + # Kill BGPd daemon on R1 + kill_router_daemons(tgen, "r1", ["bgpd"]) + + logger.info("[Step 3] : Withdraw advertised prefixes from R3...") + + # Api call to delete advertised networks + network = {"ipv4": "103.0.20.1/32", "ipv6": "3::1/128"} + for addr_type in ADDR_TYPES: + input_dict = { + "r3": { + "bgp": { + "address_family": { + addr_type: { + "unicast": { + "advertise_networks": [ + { + "network": network[addr_type], + "no_of_network": 5, + "delete": True, + } + ] + } + } + } + } + } + } + + result = create_router_bgp(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + logger.info("[Step 4] : Start BGPd daemon on R1..") + + # Start BGPd daemon on R1 + start_router_daemons(tgen, "r1", ["bgpd"]) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes before shutting down BGPd daemon + input_dict = {key: topo["routers"][key] for key in ["r3"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "r1: routes are still present in BGP RIB\n Error: {}".format( + tc_name, result + ) + ) + logger.info(" Expected behavior: {}".format(result)) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) + ) + logger.info(" Expected behavior: {}".format(result)) + + write_test_footer(tc_name) + + +def test_BGP_GR_15_p2(request): + """ + Test Objective : Test GR scenarios by enabling Graceful Restart + for multiple address families.. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r6": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r6": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + } + } + }, + "r6": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r6": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r6": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r6" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + logger.info( + "[Step 2] : Test Setup " + "[Helper Mode]R6-----R1[Restart Mode]" + "--------R2[Helper Mode] Initilized" + ) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + } + } + }, + "r2": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes + dut = "r6" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes + dut = "r6" + input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Kill BGPd daemon on R1 + kill_router_daemons(tgen, "r1", ["bgpd"]) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes + dut = "r6" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes + dut = "r6" + input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Start BGPd daemon on R1 + start_router_daemons(tgen, "r1", ["bgpd"]) + + for addr_type in ADDR_TYPES: + result = verify_bgp_convergence(tgen, topo) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes + dut = "r6" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes + dut = "r6" + input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + write_test_footer(tc_name) + + +def BGP_GR_TC_7_p1(request): + """ + Verify that BGP restarting node deletes all the routes received from peer + if BGP Graceful capability is not present in BGP Open message from the + peer + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + " Verify route download to RIB: BGP_GR_TC_7 >> " + "BGP GR [Helper Mode]R3-----R1[Restart Mode] " + ) + + # Configure graceful-restart + input_dict = { + "r3": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + "r1": { + "bgp": { + "graceful-restart": { + "graceful-restart": True, + "preserve-fw-state": True, + }, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r1": {"graceful-restart": True}}} + } + } + }, + }, + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r3" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes received from router R1 + dut = "r1" + input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + logger.info("R1 goes for reload") + kill_router_daemons(tgen, "r1", ["bgpd"]) + + # Change the configuration on router R1 + input_dict_2 = { + "r3": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-disable": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-disable": True} + } + } + } + } + }, + } + } + } + } + + result = create_router_bgp(tgen, topo, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + # Change the configuration on R1 + network = {"ipv4": "103.0.20.1/32", "ipv6": "3::1/128"} + for addr_type in ADDR_TYPES: + input_dict_2 = { + "r3": { + "bgp": { + "address_family": { + addr_type: { + "unicast": { + "advertise_networks": [ + { + "network": network[addr_type], + "no_of_network": 5, + "delete": True, + } + ] + } + } + } + } + } + } + + result = create_router_bgp(tgen, topo, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + logger.info("R1 is about to come up now") + start_router_daemons(tgen, "r1", ["bgpd"]) + logger.info("R1 is UP Now") + + # Wait for RIB stale timeout + logger.info("Verify routes are not present" "in restart router") + + for addr_type in ADDR_TYPES: + # Verifying RIB routes + dut = "r1" + input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} + result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) + ) + + write_test_footer(tc_name) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-4.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-4.py new file mode 100644 index 0000000000..889f47f377 --- /dev/null +++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-4.py @@ -0,0 +1,1024 @@ +#!/usr/bin/env python +# +# Copyright (c) 2019 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF") +# in this file. +# +# 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 VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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. +# + +""" +Following tests are covered to test BGP Graceful Restart functionality. +Basic Common Test steps for all the test case below : +- Create topology (setup module) + Creating 7 routers topology +- Bring up topology +- Verify for bgp to converge +- Configure BGP Graceful Restart on both the routers. + +TC_1_2: + Verify that EOR message is sent out only after initial convergence + Verify whether EOR message is received from all the peers after restart +TC_3: + Verify the selection deferral timer functionality when EOR is not sent + by the helper router +TC_11: + Verify that selection-deferral timer sets the maximum time to + avoid deadlock during which the best-path +TC_10: + Test Objective : Test GR scenarios on helper router by enabling + Graceful Restart for multiple address families. +TC_15: + Test Objective : Test GR scenarios by enabling Graceful Restart + for multiple address families.. +TC_16: + Test Objective : Verify BGP-GR feature when restarting node + is a transit router for it's iBGP peers. +TC_18: + Test Objective : Verify that GR helper router deletes stale routes + received from restarting node, if GR capability is not present in +TC_19: + Test Objective : Verify that GR routers keeps all the routes + received from restarting node if both the routers are +TC_26: + Test Objective : Test GR scenarios on helper router by enabling + Graceful Restart for multiple address families. +TC_28: + Test Objective : Verify if helper node goes down before restarting + node comes up online, helper node sets the R-bit to avoid dead-lock +TC_29: + Test Objective : Change timers on the fly, and + verify if it takes immediate effect. +TC_33: + Test Objective : Helper router receives same prefixes from two + different routers (GR-restarting and GR-disabled). Keeps the +TC_34_1: + Test Objective : Restarting node doesn't preserve forwarding + state, helper router should not keep the stale entries. +TC_34_2: + Test Objective : Restarting node doesn't preserve the forwarding + state verify the behaviour on helper node, if it still keeps the +TC_32: + Test Objective : Restarting node is connected to multiple helper + nodes, one of them doesn't send EOR to restarting router. Verify +TC_37: + Test Objective : Verify if helper node restarts before sending the + EOR message, restarting node doesn't wait until stale path timer +TC_30: + Test Objective : Restarting node removes stale routes from Zebra + after receiving an EOR from helper router. + +These tests have been broken up into 4 sub python scripts because +the totality of run time for this script was greater than 10 minutes +""" + +import os +import sys +import time +import pytest +from time import sleep + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join("../")) +sys.path.append(os.path.join("../lib/")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib.topogen import Topogen, get_topogen +from lib.topolog import logger + +# Required to instantiate the topology builder class. + +# Import topoJson from lib, to create topology and initial configuration +from lib.topojson import build_config_from_json +from lib.bgp import ( + clear_bgp, + verify_bgp_rib, + verify_graceful_restart, + create_router_bgp, + verify_r_bit, + verify_eor, + verify_f_bit, + verify_bgp_convergence, + verify_gr_address_family, + modify_bgp_config_when_bgpd_down, + verify_graceful_restart_timers, + verify_bgp_convergence_from_running_config, +) + +from lib.common_config import ( + write_test_header, + reset_config_on_routers, + start_topology, + kill_router_daemons, + start_router_daemons, + verify_rib, + check_address_types, + write_test_footer, + check_router_status, + step, + get_frr_ipv6_linklocal, + required_linux_kernel_version, +) + +pytestmark = [pytest.mark.bgpd] + + +# Global variables +BGP_CONVERGENCE = False +GR_RESTART_TIMER = 5 +GR_SELECT_DEFER_TIMER = 5 +GR_STALEPATH_TIMER = 5 +PREFERRED_NEXT_HOP = "link_local" +NEXT_HOP_4 = ["192.168.1.1", "192.168.4.2"] +NEXT_HOP_6 = ["fd00:0:0:1::1", "fd00:0:0:4::2"] + + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + + # Required linux kernel version for this suite to run. + result = required_linux_kernel_version("4.16") + if result is not True: + pytest.skip("Kernel requirements are not met") + + global ADDR_TYPES + + testsuite_run_time = time.asctime(time.localtime(time.time())) + logger.info("Testsuite start time: {}".format(testsuite_run_time)) + logger.info("=" * 40) + + logger.info("Running setup_module to create topology") + + # This function initiates the topology build with Topogen... + json_file = "{}/bgp_gr_topojson_topo2.json".format(CWD) + tgen = Topogen(json_file, mod.__name__) + global topo + topo = tgen.json_topo + # ... and here it calls Mininet initialization functions. + + # Starting topology, create tmp files which are loaded to routers + # to start deamons and then start routers + start_topology(tgen) + + # Creating configuration from JSON + build_config_from_json(tgen, topo) + + # Api call verify whether BGP is converged + ADDR_TYPES = check_address_types() + + for addr_type in ADDR_TYPES: + BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) + assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format( + BGP_CONVERGENCE + ) + + logger.info("Running setup_module() done") + + +def teardown_module(mod): + """ + Teardown the pytest environment + + * `mod`: module name + """ + + logger.info("Running teardown_module to delete topology") + + tgen = get_topogen() + + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + logger.info( + "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) + ) + logger.info("=" * 40) + + +def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer): + """ + This function groups the repetitive function calls into one function. + """ + + logger.info("configure_gr_followed_by_clear: dut %s peer %s", dut, peer) + + result = create_router_bgp(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"][peer]["links"][dut][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, dut, neighbor=neighbor) + + for addr_type in ADDR_TYPES: + neighbor = topo["routers"][dut]["links"][peer][addr_type].split("/")[0] + clear_bgp(tgen, addr_type, peer, neighbor=neighbor) + + result = verify_bgp_convergence_from_running_config(tgen) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + return True + + +def next_hop_per_address_family(tgen, dut, peer, addr_type, next_hop_dict): + """ + This function returns link_local or global next_hop per address-family + """ + + intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"] + if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP: + next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface) + else: + next_hop = next_hop_dict[addr_type] + + return next_hop + + +def test_BGP_GR_TC_23_p1(request): + """ + Verify that helper routers are deleting stale routes after stale route + timer's expiry. If all the routes are not received from restating node + after restart. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + "Verify Stale Routes are deleted on helper: BGP_GR_TC_23 >> " + "BGP GR [Helper Mode]R1-----R2[Restart Mode] " + ) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "graceful-restart": {"timer": {"stalepath-time": GR_STALEPATH_TIMER}}, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1": {"graceful-restart-helper": True} + } + } + } + } + }, + }, + } + }, + "r2": { + "bgp": { + "graceful-restart": { + "graceful-restart": True, + "preserve-fw-state": True, + }, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": {"dest_link": {"r2": {"graceful-restart": True}}} + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": {"dest_link": {"r2": {"graceful-restart": True}}} + } + } + }, + }, + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes received from router R1 + dut = "r1" + input_dict_1 = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + logger.info("R2 goes for reload") + kill_router_daemons(tgen, "r2", ["bgpd"]) + + # Modify configuration to delete routes and include disable-eor + input_dict_3 = {"r2": {"bgp": {"graceful-restart": {"disable-eor": True}}}} + + result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3) + + # Modify configuration to delete routes and include disable-eor + network = {"ipv4": "102.0.20.1/32", "ipv6": "2::1/128"} + for addr_type in ADDR_TYPES: + input_dict_3 = { + "r2": { + "bgp": { + "address_family": { + addr_type: { + "unicast": { + "advertise_networks": [ + { + "network": network[addr_type], + "no_of_network": 3, + "delete": True, + } + ] + } + } + } + } + } + } + + result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + logger.info("BGPd comes up for r2") + start_router_daemons(tgen, "r2", ["bgpd"]) + + # Wait for stalepath timer + logger.info("Waiting for stalepath timer({} sec..)".format(GR_STALEPATH_TIMER)) + sleep(GR_STALEPATH_TIMER) + + for addr_type in ADDR_TYPES: + clear_bgp(tgen, addr_type, "r2") + + # Verifying RIB routes + dut = "r1" + network = {"ipv4": "102.0.20.4/32", "ipv6": "2::4/128"} + for addr_type in ADDR_TYPES: + input_dict_1 = { + "r1": { + "bgp": { + "address_family": { + addr_type: { + "unicast": { + "advertise_networks": [ + {"network": network[addr_type], "no_of_network": 2} + ] + } + } + } + } + } + } + + # Verify EOR on helper router + result = verify_eor( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format( + tc_name, result + ) + + # Verifying BGP RIB routes received from router R1 + dut = "r1" + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + write_test_footer(tc_name) + + +def test_BGP_GR_20_p1(request): + """ + Test Objective : Verify that GR routers delete all the routes + received from a node if both the routers are configured as GR + helper node + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + "[Step 1] : Test Setup " "[Restart Mode]R3-----R1[Restart Mode] Initilized" + ) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + "r3": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r3" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes + dut = "r3" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Kill BGPd daemon on R1 + kill_router_daemons(tgen, "r1", ["bgpd"]) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes + dut = "r3" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "r3: routes are still present in BGP RIB\n Error: {}".format( + tc_name, result + ) + ) + logger.info(" Expected behavior: {}".format(result)) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) + ) + logger.info(" Expected behavior: {}".format(result)) + + # Start BGPd daemon on R1 + start_router_daemons(tgen, "r1", ["bgpd"]) + + for addr_type in ADDR_TYPES: + result = verify_bgp_convergence(tgen, topo) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes + dut = "r3" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + write_test_footer(tc_name) + + +def test_BGP_GR_21_p2(request): + """ + Test Objective : VVerify BGP-GR feature when helper node is + a transit router for it's eBGP peers. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + "[Step 1] : Test Setup " "[Helper Mode]R6-----R1[Restart Mode] Initilized" + ) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r6": { + "dest_link": { + "r1": {"graceful-restart-disable": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r6": { + "dest_link": { + "r1": {"graceful-restart-disable": True} + } + } + } + } + }, + } + } + }, + "r6": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r6": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r6": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r6" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + logger.info( + "[Step 2] : Test Setup " + "[Restart Mode]R2-----[Helper Mode]R1[Disable Mode]" + "--------R6[Helper Mode] Initilized" + ) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + "r2": { + "bgp": { + "graceful-restart": { + "graceful-restart": True, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes + dut = "r6" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes + dut = "r6" + input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Kill BGPd daemon on R1 + kill_router_daemons(tgen, "r2", ["bgpd"]) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes + dut = "r6" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes + dut = "r6" + input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Start BGPd daemon on R1 + start_router_daemons(tgen, "r2", ["bgpd"]) + + for addr_type in ADDR_TYPES: + result = verify_bgp_convergence(tgen, topo) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes + dut = "r6" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes after bringing up BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes + dut = "r6" + input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + write_test_footer(tc_name) + + +def test_BGP_GR_22_p2(request): + """ + Test Objective : Verify BGP-GR feature when helper node + is a transit router for it's iBGP peers. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + # Check router status + check_router_status(tgen) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Creating configuration from JSON + reset_config_on_routers(tgen) + + logger.info( + "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] Initilized" + ) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1": { + "graceful-restart-disable": True, + "next_hop_self": True, + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1": { + "graceful-restart-disable": True, + "next_hop_self": True, + } + } + } + } + } + }, + } + } + }, + "r3": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r3" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + logger.info( + "[Step 2] : Test Setup " + "[Restart Mode]R2-----[Helper Mode]R1[Disable Mode]" + "--------R3[Helper Mode] Initilized" + ) + + # Configure graceful-restart + input_dict = { + "r1": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1": {"graceful-restart-helper": True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1": {"graceful-restart-helper": True} + } + } + } + } + }, + } + } + }, + "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, + } + + configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") + + for addr_type in ADDR_TYPES: + result = verify_graceful_restart( + tgen, topo, addr_type, input_dict, dut="r1", peer="r2" + ) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes + dut = "r3" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes + dut = "r3" + input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Kill BGPd daemon on R1 + kill_router_daemons(tgen, "r2", ["bgpd"]) + + for addr_type in ADDR_TYPES: + # Verifying BGP RIB routes + dut = "r3" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes + dut = "r3" + input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Start BGPd daemon on R1 + start_router_daemons(tgen, "r2", ["bgpd"]) + + for addr_type in ADDR_TYPES: + result = verify_bgp_convergence(tgen, topo) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes + dut = "r3" + input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying BGP RIB routes + dut = "r3" + input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + # Verifying RIB routes before shutting down BGPd daemon + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + write_test_footer(tc_name) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py deleted file mode 100644 index 52ad7813c5..0000000000 --- a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py +++ /dev/null @@ -1,4358 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2019 by VMware, Inc. ("VMware") -# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF") -# in this file. -# -# 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 VMWARE DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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. -# - -""" -Following tests are covered to test BGP Graceful Restart functionality. -Basic Common Test steps for all the test case below : -- Create topology (setup module) - Creating 7 routers topology -- Bring up topology -- Verify for bgp to converge -- Configure BGP Graceful Restart on both the routers. - -TC_1_2: - Verify that EOR message is sent out only after initial convergence - Verify whether EOR message is received from all the peers after restart -TC_3: - Verify the selection deferral timer functionality when EOR is not sent - by the helper router -TC_11: - Verify that selection-deferral timer sets the maximum time to - avoid deadlock during which the best-path -TC_10: - Test Objective : Test GR scenarios on helper router by enabling - Graceful Restart for multiple address families. -TC_15: - Test Objective : Test GR scenarios by enabling Graceful Restart - for multiple address families.. -TC_16: - Test Objective : Verify BGP-GR feature when restarting node - is a transit router for it's iBGP peers. -TC_18: - Test Objective : Verify that GR helper router deletes stale routes - received from restarting node, if GR capability is not present in -TC_19: - Test Objective : Verify that GR routers keeps all the routes - received from restarting node if both the routers are -TC_26: - Test Objective : Test GR scenarios on helper router by enabling - Graceful Restart for multiple address families. -TC_28: - Test Objective : Verify if helper node goes down before restarting - node comes up online, helper node sets the R-bit to avoid dead-lock -TC_29: - Test Objective : Change timers on the fly, and - verify if it takes immediate effect. -TC_33: - Test Objective : Helper router receives same prefixes from two - different routers (GR-restarting and GR-disabled). Keeps the -TC_34_1: - Test Objective : Restarting node doesn't preserve forwarding - state, helper router should not keep the stale entries. -TC_34_2: - Test Objective : Restarting node doesn't preserve the forwarding - state verify the behaviour on helper node, if it still keeps the -TC_32: - Test Objective : Restarting node is connected to multiple helper - nodes, one of them doesn't send EOR to restarting router. Verify -TC_37: - Test Objective : Verify if helper node restarts before sending the - EOR message, restarting node doesn't wait until stale path timer -TC_30: - Test Objective : Restarting node removes stale routes from Zebra - after receiving an EOR from helper router. - -""" - -import os -import sys -import time -import pytest -from time import sleep - -# Save the Current Working Directory to find configuration files. -CWD = os.path.dirname(os.path.realpath(__file__)) -sys.path.append(os.path.join("../")) -sys.path.append(os.path.join("../lib/")) - -# pylint: disable=C0413 -# Import topogen and topotest helpers -from lib.topogen import Topogen, get_topogen -from lib.topolog import logger - -# Required to instantiate the topology builder class. - -# Import topoJson from lib, to create topology and initial configuration -from lib.topojson import build_config_from_json -from lib.bgp import ( - clear_bgp, - verify_bgp_rib, - verify_graceful_restart, - create_router_bgp, - verify_r_bit, - verify_eor, - verify_f_bit, - verify_bgp_convergence, - verify_gr_address_family, - modify_bgp_config_when_bgpd_down, - verify_graceful_restart_timers, - verify_bgp_convergence_from_running_config, -) - -from lib.common_config import ( - write_test_header, - reset_config_on_routers, - start_topology, - kill_router_daemons, - start_router_daemons, - verify_rib, - check_address_types, - write_test_footer, - check_router_status, - step, - get_frr_ipv6_linklocal, - required_linux_kernel_version, -) - -pytestmark = [pytest.mark.bgpd] - - -# Global variables -BGP_CONVERGENCE = False -GR_RESTART_TIMER = 5 -GR_SELECT_DEFER_TIMER = 5 -GR_STALEPATH_TIMER = 5 -PREFERRED_NEXT_HOP = "link_local" -NEXT_HOP_4 = ["192.168.1.1", "192.168.4.2"] -NEXT_HOP_6 = ["fd00:0:0:1::1", "fd00:0:0:4::2"] - - -def setup_module(mod): - """ - Sets up the pytest environment - - * `mod`: module name - """ - - # Required linux kernel version for this suite to run. - result = required_linux_kernel_version("4.16") - if result is not True: - pytest.skip("Kernel requirements are not met") - - global ADDR_TYPES - - testsuite_run_time = time.asctime(time.localtime(time.time())) - logger.info("Testsuite start time: {}".format(testsuite_run_time)) - logger.info("=" * 40) - - logger.info("Running setup_module to create topology") - - # This function initiates the topology build with Topogen... - json_file = "{}/bgp_gr_topojson_topo2.json".format(CWD) - tgen = Topogen(json_file, mod.__name__) - global topo - topo = tgen.json_topo - # ... and here it calls Mininet initialization functions. - - # Starting topology, create tmp files which are loaded to routers - # to start deamons and then start routers - start_topology(tgen) - - # Creating configuration from JSON - build_config_from_json(tgen, topo) - - # Api call verify whether BGP is converged - ADDR_TYPES = check_address_types() - - for addr_type in ADDR_TYPES: - BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) - assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format( - BGP_CONVERGENCE - ) - - logger.info("Running setup_module() done") - - -def teardown_module(mod): - """ - Teardown the pytest environment - - * `mod`: module name - """ - - logger.info("Running teardown_module to delete topology") - - tgen = get_topogen() - - # Stop toplogy and Remove tmp files - tgen.stop_topology() - - logger.info( - "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) - ) - logger.info("=" * 40) - - -def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer): - """ - This function groups the repetitive function calls into one function. - """ - - logger.info("configure_gr_followed_by_clear: dut %s peer %s", dut, peer) - - result = create_router_bgp(tgen, topo, input_dict) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - for addr_type in ADDR_TYPES: - neighbor = topo["routers"][peer]["links"][dut][addr_type].split("/")[0] - clear_bgp(tgen, addr_type, dut, neighbor=neighbor) - - for addr_type in ADDR_TYPES: - neighbor = topo["routers"][dut]["links"][peer][addr_type].split("/")[0] - clear_bgp(tgen, addr_type, peer, neighbor=neighbor) - - result = verify_bgp_convergence_from_running_config(tgen) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - return True - - -def next_hop_per_address_family(tgen, dut, peer, addr_type, next_hop_dict): - """ - This function returns link_local or global next_hop per address-family - """ - - intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"] - if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP: - next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface) - else: - next_hop = next_hop_dict[addr_type] - - return next_hop - - -def test_BGP_GR_TC_1_2_p0(request): - """ - Verify that EOR message is sent out only after initial convergence - Verify whether EOR message is received from all the peers after restart - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - "Verify EOR Sent and Received : BGP_GR_TC_1_2 >> " - "BGP GR [Helper Mode]R3-----R1[Restart Mode] " - ) - - # Configure graceful-restart - input_dict = { - "r3": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - "r1": { - "bgp": { - "graceful-restart": { - "graceful-restart": True, - "preserve-fw-state": True, - }, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - }, - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r3" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes received from router R3 - dut = "r1" - input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("R1 goes for reload") - kill_router_daemons(tgen, "r1", ["bgpd"]) - - for addr_type in ADDR_TYPES: - # Verifying RIB routes - input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} - # Verifying RIB routes - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("Starting bgpd process") - start_router_daemons(tgen, "r1", ["bgpd"]) - logger.info("R1 is UP Now") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r3" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes received from router R3 - input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying EOR on restarting router - result = verify_eor(tgen, topo, addr_type, input_dict, dut="r3", peer="r1") - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - write_test_footer(tc_name) - - -def test_BGP_GR_TC_3_p0(request): - """ - Verify the selection deferral timer functionality when EOR is not sent - by the helper router - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - " Verify route download to RIB: BGP_GR_TC_3 >> " - "BGP GR [Helper Mode]R1-----R2[Restart Mode] " - ) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "graceful-restart": { - "disable-eor": True, - }, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1": {"graceful-restart-helper": True} - } - } - } - } - }, - }, - } - }, - "r2": { - "bgp": { - "graceful-restart": { - "graceful-restart": True, - "preserve-fw-state": True, - "timer": {"select-defer-time": GR_SELECT_DEFER_TIMER}, - }, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": {"dest_link": {"r2": {"graceful-restart": True}}} - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": {"dest_link": {"r2": {"graceful-restart": True}}} - } - } - }, - }, - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes received from router R1 - dut = "r2" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("R2 goes for reload ") - kill_router_daemons(tgen, "r2", ["bgpd"]) - - logger.info("R2 is about to come up now") - start_router_daemons(tgen, "r2", ["bgpd"]) - logger.info("R2 is UP Now") - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes received from router R1 - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verify EOR on restarting router - result = verify_eor( - tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False - ) - assert ( - result is not True - ), "Testcase {} : Failed \n " "r2: EOR is set to True\n Error: {}".format( - tc_name, result - ) - - logger.info( - "Waiting for selection deferral timer({} sec)..".format(GR_SELECT_DEFER_TIMER) - ) - sleep(GR_SELECT_DEFER_TIMER) - - for addr_type in ADDR_TYPES: - # Verifying RIB routes - result = verify_rib(tgen, addr_type, "r2", input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - write_test_footer(tc_name) - - -def test_BGP_GR_TC_11_p0(request): - """ - Verify that selection-deferral timer sets the maximum time to - avoid deadlock during which the best-path - selection process is deferred, after a peer session was restarted - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info("Verify EOR Sent after deferral timeout : BGP_GR_TC_11") - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "graceful-restart": { - "graceful-restart": True, - "select-defer-time": GR_SELECT_DEFER_TIMER, - }, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": {"dest_link": {"r1": {"graceful-restart": True}}}, - "r3": {"dest_link": {"r1": {"graceful-restart": True}}}, - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": {"dest_link": {"r1": {"graceful-restart": True}}}, - "r3": {"dest_link": {"r1": {"graceful-restart": True}}}, - } - } - }, - }, - } - }, - "r3": { - "bgp": { - "graceful-restart": {"disable-eor": True}, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - }, - } - }, - } - - result = create_router_bgp(tgen, topo, input_dict) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - for addr_type in ADDR_TYPES: - clear_bgp(tgen, addr_type, "r1") - clear_bgp(tgen, addr_type, "r3") - - result = verify_bgp_convergence_from_running_config(tgen, topo) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r3" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes received from router R1 - dut = "r1" - input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("R1 goes for reload") - kill_router_daemons(tgen, "r1", ["bgpd"]) - - logger.info("Starting bgpd process") - start_router_daemons(tgen, "r1", ["bgpd"]) - logger.info("R1 is UP Now") - - for addr_type in ADDR_TYPES: - # Verify EOR on restarting router - result = verify_eor( - tgen, topo, addr_type, input_dict, dut="r1", peer="r3", expected=False - ) - assert ( - result is not True - ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format( - tc_name, result - ) - - logger.info( - "Waiting for selection deferral timer({} sec).. ".format( - GR_SELECT_DEFER_TIMER + 2 - ) - ) - sleep(GR_SELECT_DEFER_TIMER + 2) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes received from router R1 - input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying EOR on restarting router - result = verify_eor( - tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False - ) - assert ( - result is not True - ), "Testcase {} : Failed \n " "r3: EOR is set to True\n Error: {}".format( - tc_name, result - ) - - write_test_footer(tc_name) - - -def test_BGP_GR_10_p2(request): - """ - Test Objective : Test GR scenarios on helper router by enabling - Graceful Restart for multiple address families. - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - step("Test Setup: [Helper Mode]R3-----R1[Restart Mode] initialized") - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r3": { - "dest_link": { - "r1": { - "next_hop_self": True, - "graceful-restart": True, - "activate": "ipv6", - } - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r3": { - "dest_link": { - "r1": { - "next_hop_self": True, - "graceful-restart": True, - "activate": "ipv4", - } - } - } - } - } - }, - } - } - }, - "r3": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": { - "graceful-restart-helper": True, - "activate": "ipv6", - } - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": { - "graceful-restart-helper": True, - "activate": "ipv4", - } - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") - - for addr_type in ADDR_TYPES: - step( - "Verifying GR config and operational state for addr_type {}".format( - addr_type - ) - ) - - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r3" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes - dut = "r3" - input_topo = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_topo) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # verify multi address family - result = verify_gr_address_family( - tgen, - topo, - addr_type, - "ipv4Unicast", - dut="r1", - peer="r3", - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # verify multi address family - result = verify_gr_address_family( - tgen, - topo, - addr_type, - "ipv6Unicast", - dut="r1", - peer="r3", - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # verify multi address family - result = verify_gr_address_family( - tgen, - topo, - addr_type, - "ipv4Unicast", - dut="r3", - peer="r1", - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # verify multi address family - result = verify_gr_address_family( - tgen, - topo, - addr_type, - "ipv6Unicast", - dut="r3", - peer="r1", - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - step("Killing bgpd on r1") - - # Kill BGPd daemon on R1 - kill_router_daemons(tgen, "r1", ["bgpd"]) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes - input_topo = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_topo) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - step("Starting bgpd on r1") - - # Start BGPd daemon on R1 - start_router_daemons(tgen, "r1", ["bgpd"]) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes - input_topo = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_topo) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - write_test_footer(tc_name) - - -def BGP_GR_16_p2(request): - """ - Test Objective : Verify BGP-GR feature when restarting node - is a transit router for it's iBGP peers. - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] initialized" - ) - - # Configure graceful-restart and timers - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r3": { - "dest_link": { - "r1": { - "graceful-restart": True, - "next_hop_self": True, - } - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r3": { - "dest_link": { - "r1": { - "graceful-restart": True, - "next_hop_self": True, - } - } - } - } - } - }, - } - } - }, - "r3": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r3" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info( - "[Step 2] : Test Setup " - "[Helper Mode]R3-----R1[Restart Mode]" - "--------R6[Helper Mode] initialized" - ) - - # Configure graceful-restart and timers - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - } - } - }, - "r2": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r2": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r2": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes - dut = "r3" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes - input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Kill BGPd daemon on R1 - kill_router_daemons(tgen, "r1", ["bgpd"]) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes - input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Start BGPd daemon on R1 - start_router_daemons(tgen, "r1", ["bgpd"]) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes - input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - result = verify_bgp_convergence_from_running_config(tgen, topo) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - write_test_footer(tc_name) - - -def test_BGP_GR_18_p1(request): - """ - Test Objective : Verify that GR helper router deletes stale routes - received from restarting node, if GR capability is not present in - restarting node's OPEN message. - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - "[Step 1] : Test Setup " "[Helper Mode]R6-----R1[Restart Mode] initialized" - ) - - # Configure graceful-restart and timers - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r6": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r6": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - } - } - }, - "r6": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r6": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r6": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r6" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info( - "[Step 2] : Test Setup " - "[Helper Mode]R6-----R1[Restart Mode]" - "--------R2[Helper Mode] initialized" - ) - - # Configure graceful-restart and timers - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - } - } - }, - "r2": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r2": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r2": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes - dut = "r6" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes - dut = "r2" - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Kill BGPd daemon on R1 - kill_router_daemons(tgen, "r1", ["bgpd"]) - - logger.info("[Step 3] : Configure R1 to prevent sending EOR") - - # Modify graceful-restart config to prevent sending EOR - input_dict_3 = {"r1": {"bgp": {"graceful-restart": {"disable-eor": True}}}} - - result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3) - - # Modify configuration to delete routes - network = {"ipv4": "101.0.20.1/32", "ipv6": "1::1/128"} - for addr_type in ADDR_TYPES: - input_dict_3 = { - "r1": { - "bgp": { - "address_family": { - addr_type: { - "unicast": { - "advertise_networks": [ - { - "network": network[addr_type], - "no_of_network": 5, - "delete": True, - } - ] - } - } - } - } - } - } - - result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Modify graceful-restart config - input_dict_3 = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1": {"graceful-restart-disable": True} - } - }, - "r6": { - "dest_link": { - "r1": {"graceful-restart-disable": True} - } - }, - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1": {"graceful-restart-disable": True} - } - }, - "r6": { - "dest_link": { - "r1": {"graceful-restart-disable": True} - } - }, - } - } - }, - } - } - } - } - - result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3) - assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result) - - logger.info("[Step 4] : Bring up the BGPd daemon on R1 for 30" " seconds..") - - # Start BGPd daemon on R1 - start_router_daemons(tgen, "r1", ["bgpd"]) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes - dut = "r6" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False) - assert result is not True, ( - "Testcase {} : Failed \n " - "r6: routes are still present in BGP RIB\n Error: {}".format( - tc_name, result - ) - ) - logger.info(" Expected behavior: {}".format(result)) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False) - assert result is not True, ( - "Testcase {} : Failed \n " - "r6: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) - ) - logger.info(" Expected behavior: {}".format(result)) - - # Verifying BGP RIB routes - dut = "r2" - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False) - assert result is not True, ( - "Testcase {} : Failed \n " - "r2: routes are still present in BGP RIB\n Error: {}".format( - tc_name, result - ) - ) - logger.info(" Expected behavior: {}".format(result)) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False) - assert result is not True, ( - "Testcase {} : Failed \n " - "r6: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) - ) - logger.info(" Expected behavior: {}".format(result)) - - write_test_footer(tc_name) - - -def test_BGP_GR_26_p2(request): - """ - Test Objective : Test GR scenarios on helper router by enabling - Graceful Restart for multiple address families. - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] initialized" - ) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r3": { - "dest_link": { - "r1": { - "graceful-restart": True, - "next_hop_self": True, - "activate": "ipv6", - } - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r3": { - "dest_link": { - "r1": { - "graceful-restart": True, - "next_hop_self": True, - "activate": "ipv4", - } - } - } - } - } - }, - } - } - }, - "r3": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": { - "graceful-restart-helper": True, - "activate": "ipv6", - } - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": { - "graceful-restart-helper": True, - "activate": "ipv4", - } - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r3", peer="r1" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes - dut = "r3" - input_topo = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_topo) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Kill BGPd daemon on R1 - kill_router_daemons(tgen, "r1", ["bgpd"]) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes - input_topo = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_topo) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Start BGPd daemon on R1 - start_router_daemons(tgen, "r1", ["bgpd"]) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes - input_topo = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_topo) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_topo) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # verify multi address family - result = verify_gr_address_family( - tgen, - topo, - addr_type, - "ipv4Unicast", - dut="r1", - peer="r3", - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # verify multi address family - result = verify_gr_address_family( - tgen, - topo, - addr_type, - "ipv6Unicast", - dut="r1", - peer="r3", - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # verify multi address family - result = verify_gr_address_family( - tgen, - topo, - addr_type, - "ipv4Unicast", - dut="r3", - peer="r1", - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # verify multi address family - result = verify_gr_address_family( - tgen, - topo, - addr_type, - "ipv6Unicast", - dut="r3", - peer="r1", - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - write_test_footer(tc_name) - - -def test_BGP_GR_chaos_28_p1(request): - """ - Test Objective : Verify if helper node goes down before restarting - node comes up online, helper node sets the R-bit to avoid dead-lock - till SDT expiry. - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - "Test Case: test_BGP_GR_chaos_28 :" - "[Helper Mode]R3-----R1[Restart Mode] initialized" - ) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - } - } - }, - "r3": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r3" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("[Step 1] : Kill BGPd daemon on R1..") - - # Kill BGPd daemon on R1 - kill_router_daemons(tgen, "r1", ["bgpd"]) - - logger.info("[Step 2] : Kill BGPd daemon on R3..") - - # Kill BGPd daemon on R3 - kill_router_daemons(tgen, "r3", ["bgpd"]) - - logger.info("[Step 3] : Start BGPd daemon on R1..") - - # Start BGPd daemon on R1 - start_router_daemons(tgen, "r1", ["bgpd"]) - - logger.info("[Step 4] : Start BGPd daemon on R3..") - - # Start BGPd daemon on R3 - start_router_daemons(tgen, "r3", ["bgpd"]) - - # Verify r_bit - for addr_type in ADDR_TYPES: - result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r3", peer="r1") - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - write_test_footer(tc_name) - - -def test_BGP_GR_chaos_29_p1(request): - """ - Test Objective : Change timers on the fly, and - verify if it takes immediate effect. - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - " Test Case : test_BGP_GR_chaos_29" - " BGP GR [Helper Mode]R3-----R1[Restart Mode]" - " and [restart-time 150]R1 initialized" - ) - - # Configure graceful-restart and timers - input_dict = { - "r1": { - "bgp": { - "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER}}, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - }, - } - }, - "r3": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r3" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verify graceful-restart timers - input_dict_2 = { - "r1": { - "bgp": { - "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER + 5}} - } - } - } - - result = create_router_bgp(tgen, topo, input_dict_2) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - for addr_type in ADDR_TYPES: - input_dict_2 = { - "r1": { - "bgp": { - "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER}} - } - } - } - - result = verify_graceful_restart_timers( - tgen, topo, addr_type, input_dict_2, dut="r3", peer="r1" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes before shutting down BGPd daemon - dut = "r3" - input_dict = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("[Step 2] : Kill BGPd daemon on R1..") - - # Kill BGPd daemon on R1 - kill_router_daemons(tgen, "r1", ["bgpd"]) - - logger.info("[Step 3] : Wait for {} seconds..".format(GR_RESTART_TIMER)) - - # Waiting for GR_RESTART_TIMER - sleep(GR_RESTART_TIMER) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes before shutting down BGPd daemon - input_dict = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False) - assert result is not True, ( - "Testcase {} : Failed \n " - "r3: routes are still present in BGP RIB\n Error: {}".format( - tc_name, result - ) - ) - logger.info(" Expected behavior: {}".format(result)) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict, expected=False) - assert result is not True, ( - "Testcase {} : Failed \n " - "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) - ) - logger.info(" Expected behavior: {}".format(result)) - - logger.info("[Step 4] : Start BGPd daemon on R1..") - - # Start BGPd daemon on R1 - start_router_daemons(tgen, "r1", ["bgpd"]) - - write_test_footer(tc_name) - - -def test_BGP_GR_chaos_33_p1(request): - """ - Test Objective : Helper router receives same prefixes from two - different routers (GR-restarting and GR-disabled). Keeps the - stale entry only for GR-restarting node(next-hop is correct). - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - " Test Case : test_BGP_GR_chaos_33 " - "BGP GR " - "[Restart Mode]R1--R3[Helper Mode]--R4[Disabled Mode]" - ) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - } - } - }, - "r3": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - "r4": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r3": { - "dest_link": { - "r4": {"graceful-restart-disable": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r3": { - "dest_link": { - "r4": {"graceful-restart-disable": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r3" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("[Step 2] : Advertise same networks from R1 and R4..") - - # Api call to delete advertised networks - input_dict_2 = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "advertise_networks": [ - { - "network": "200.0.20.1/32", - "no_of_network": 2, - } - ] - } - }, - "ipv6": { - "unicast": { - "advertise_networks": [ - {"network": "2001::1/128", "no_of_network": 2} - ] - } - }, - } - } - }, - "r4": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "advertise_networks": [ - {"network": "200.0.20.1/32", "no_of_network": 2} - ] - } - }, - "ipv6": { - "unicast": { - "advertise_networks": [ - {"network": "2001::1/128", "no_of_network": 2} - ] - } - }, - } - } - }, - } - - result = create_router_bgp(tgen, topo, input_dict_2) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - for addr_type in ADDR_TYPES: - # Verifying RIB routes - dut = "r3" - peer1 = "r1" - peer2 = "r4" - intf1 = topo["routers"][peer1]["links"][dut]["interface"] - intf2 = topo["routers"][peer2]["links"][dut]["interface"] - - if addr_type == "ipv4": - next_hop_4 = NEXT_HOP_4 - result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_4) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - if addr_type == "ipv6": - if "link_local" in PREFERRED_NEXT_HOP: - next_hop1 = get_frr_ipv6_linklocal(tgen, peer1, intf=intf1) - next_hop2 = get_frr_ipv6_linklocal(tgen, peer2, intf=intf2) - - next_hop_6 = [next_hop1, next_hop2] - else: - next_hop_6 = NEXT_HOP_6 - - result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_6) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("[Step 3] : Kill BGPd daemon on R1 and R4..") - - # Kill BGPd daemon on R1 - kill_router_daemons(tgen, "r1", ["bgpd"]) - - # Kill BGPd daemon on R4 - kill_router_daemons(tgen, "r4", ["bgpd"]) - - for addr_type in ADDR_TYPES: - # Verifying RIB routes - next_hop_6 = ["fd00:0:0:1::1"] - if addr_type == "ipv4": - next_hop_4 = NEXT_HOP_4[0] - - result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_4) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - if addr_type == "ipv6": - if "link_local" in PREFERRED_NEXT_HOP: - next_hop_6 = get_frr_ipv6_linklocal(tgen, peer1, intf=intf1) - else: - next_hop_6 = NEXT_HOP_6[0] - - result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_6) - - # Verifying RIB routes - if addr_type == "ipv4": - next_hop_4 = NEXT_HOP_4[1] - result = verify_rib( - tgen, addr_type, dut, input_dict_2, next_hop_4, expected=False - ) - assert result is not True, ( - "Testcase {} : Failed \n " - "r3: routes are still present in BGP RIB\n Error: {}".format( - tc_name, result - ) - ) - logger.info(" Expected behavior: {}".format(result)) - - if addr_type == "ipv6": - if "link_local" in PREFERRED_NEXT_HOP: - next_hop_6 = get_frr_ipv6_linklocal(tgen, peer2, intf=intf2) - else: - next_hop_6 = NEXT_HOP_6[1] - - result = verify_rib( - tgen, addr_type, dut, input_dict_2, next_hop_6, expected=False - ) - assert result is not True, ( - "Testcase {} : Failed \n " - "r3: routes are still present in ZEBRA\n Error: {}".format( - tc_name, result - ) - ) - logger.info(" Expected behavior: {}".format(result)) - - logger.info("[Step 4] : Start BGPd daemon on R1 and R4..") - - # Start BGPd daemon on R1 - start_router_daemons(tgen, "r1", ["bgpd"]) - - # Start BGPd daemon on R4 - start_router_daemons(tgen, "r4", ["bgpd"]) - - write_test_footer(tc_name) - - -def test_BGP_GR_chaos_34_2_p1(request): - """ - Test Objective : Restarting node doesn't preserve the forwarding - state verify the behaviour on helper node, if it still keeps the - stale routes. - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - " Test Case : test_BGP_GR_chaos_34 " - "BGP GR " - "[Restart Mode]R1---R3[Helper Mode]" - ) - - logger.info("[Step 1] : Configure restarting" " router R1 to prevent ") - logger.info("[Step 2] : Reset the session" " between R1 and R3..") - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "graceful-restart": {"preserve-fw-state": True, "disable-eor": True}, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - }, - } - }, - "r3": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r3" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verify f-bit before killing BGPd daemon - result = verify_f_bit(tgen, topo, addr_type, input_dict, "r3", "r1") - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes after starting BGPd daemon - dut = "r3" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("[Step 3] : Kill BGPd daemon on R1..") - - # Kill BGPd daemon on R1 - kill_router_daemons(tgen, "r1", ["bgpd"]) - - logger.info("[Step 4] : Withdraw/delete the prefixes " "originated from R1..") - - # Api call to delete advertised networks - network = {"ipv4": "101.0.20.1/32", "ipv6": "1::1/128"} - for addr_type in ADDR_TYPES: - input_dict_2 = { - "r1": { - "bgp": { - "address_family": { - addr_type: { - "unicast": { - "advertise_networks": [ - { - "network": network[addr_type], - "no_of_network": 5, - "delete": True, - } - ] - } - } - } - } - } - } - - result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("[Step 5] : Remove the CLI from R1's config to " "set the F-bit..") - - # Modify graceful-restart config not to set f-bit - # and write to /etc/frr - input_dict_2 = {"r1": {"bgp": {"graceful-restart": {"preserve-fw-state": False}}}} - - result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2) - assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result) - - logger.info("[Step 6] : Bring up the BGPd daemon on R1 again..") - - # Start BGPd daemon on R1 - start_router_daemons(tgen, "r1", ["bgpd"]) - - for addr_type in ADDR_TYPES: - # Verify f-bit after starting BGPd daemon - result = verify_f_bit( - tgen, topo, addr_type, input_dict, "r3", "r1", expected=False - ) - assert ( - result is not True - ), "Testcase {} : Failed \n " "r3: F-bit is set to True\n Error: {}".format( - tc_name, result - ) - logger.info(" Expected behavior: {}".format(result)) - - # Verifying BGP RIB routes after starting BGPd daemon - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False) - assert result is not True, ( - "Testcase {} : Failed \n " - "r3: routes are still present in BGP RIB\n Error: {}".format( - tc_name, result - ) - ) - logger.info(" Expected behavior: {}".format(result)) - - # Verifying RIB routes - result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False) - assert result is not True, ( - "Testcase {} : Failed \n " - "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) - ) - logger.info(" Expected behavior: {}".format(result)) - - write_test_footer(tc_name) - - -def test_BGP_GR_chaos_34_1_p1(request): - """ - Test Objective : Restarting node doesn't preserve forwarding - state, helper router should not keep the stale entries. - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - " Test Case : test_BGP_GR_chaos_31 " - "BGP GR " - "[Restart Mode]R1---R3[Helper Mode]" - ) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "graceful-restart": { - "preserve-fw-state": True, - "timer": {"restart-time": GR_RESTART_TIMER}, - }, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - }, - } - }, - "r3": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r3" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes after starting BGPd daemon - dut = "r3" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info( - "[Step 1] : Remove the preserve-fw-state command" - " from restarting node R1's config" - ) - - # Configure graceful-restart to set f-bit as False - input_dict_2 = {"r1": {"bgp": {"graceful-restart": {"preserve-fw-state": False}}}} - - result = create_router_bgp(tgen, topo, input_dict_2) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - logger.info("[Step 2] : Reset the session between R1 and R3..") - - # Reset sessions - for addr_type in ADDR_TYPES: - clear_bgp(tgen, addr_type, "r1") - - result = verify_bgp_convergence_from_running_config(tgen, topo) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - for addr_type in ADDR_TYPES: - # Verify f-bit after starting BGPd daemon - result = verify_f_bit( - tgen, topo, addr_type, input_dict_2, "r3", "r1", expected=False - ) - assert ( - result is not True - ), "Testcase {} : Failed \n " "r3: F-bit is set to True\n Error: {}".format( - tc_name, result - ) - logger.info(" Expected behavior: {}".format(result)) - - logger.info("[Step 3] : Kill BGPd daemon on R1..") - - # Kill BGPd daemon on R1 - kill_router_daemons(tgen, "r1", ["bgpd"]) - - # Waiting for GR_RESTART_TIMER - logger.info("Waiting for {} sec..".format(GR_RESTART_TIMER)) - sleep(GR_RESTART_TIMER) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes - input_dict = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False) - assert result is not True, ( - "Testcase {} : Failed \n " - "r3: routes are still present in BGP RIB\n Error: {}".format( - tc_name, result - ) - ) - logger.info(" Expected behavior: {}".format(result)) - - # Verifying RIB routes - result = verify_rib(tgen, addr_type, dut, input_dict, expected=False) - assert result is not True, ( - "Testcase {} : Failed \n " - "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) - ) - logger.info(" Expected behavior: {}".format(result)) - - # Start BGPd daemon on R1 - start_router_daemons(tgen, "r1", ["bgpd"]) - - write_test_footer(tc_name) - - -def test_BGP_GR_chaos_32_p1(request): - """ - Test Objective : Restarting node is connected to multiple helper - nodes, one of them doesn't send EOR to restarting router. Verify - that only after SDT restarting node send EOR to all helper peers - excluding the prefixes originated by faulty router. - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - " Test Case : test_BGP_GR_chaos_32 " - "BGP GR " - "[Restart Mode]R1---R3&R5[Helper Mode]" - ) - - logger.info( - "[Step 1] : Change the mode on R1 be a restarting" " node on global level" - ) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "graceful-restart": {"graceful-restart": True}, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"next_hop_self": True}}}, - "r5": {"dest_link": {"r1": {"graceful-restart": True}}}, - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"next_hop_self": True}}}, - "r5": {"dest_link": {"r1": {"graceful-restart": True}}}, - } - } - }, - }, - } - }, - "r5": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r5": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r5": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r5") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r5" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes after starting BGPd daemon - dut = "r3" - input_dict_1 = {key: topo["routers"][key] for key in ["r5"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("[Step 2] : Kill BGPd daemon on R1..") - # Kill BGPd daemon on R1 - kill_router_daemons(tgen, "r1", ["bgpd"]) - - logger.info("[Step 3] : Withdraw all the advertised prefixes from R5") - - # Api call to delete advertised networks - network = {"ipv4": "105.0.20.1/32", "ipv6": "5::1/128"} - for addr_type in ADDR_TYPES: - input_dict_2 = { - "r5": { - "bgp": { - "address_family": { - addr_type: { - "unicast": { - "advertise_networks": [ - { - "network": network[addr_type], - "no_of_network": 5, - "delete": True, - } - ] - } - } - } - } - } - } - - result = create_router_bgp(tgen, topo, input_dict_2) - assert result is True, "Testcase {} : Failed \n Error: {}".format( - tc_name, result - ) - - logger.info( - "[Step 4] : Stop the helper router R5 from sending EOR" " message using CLI" - ) - - # Modify graceful-restart config to prevent sending EOR - input_dict_3 = {"r5": {"bgp": {"graceful-restart": {"disable-eor": True}}}} - - result = create_router_bgp(tgen, topo, input_dict_3) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - logger.info("[Step 5] : Bring up the BGPd daemon on R1..") - - # Start BGPd daemon on R1 - start_router_daemons(tgen, "r1", ["bgpd"]) - - for addr_type in ADDR_TYPES: - # Verify EOR is disabled - result = verify_eor( - tgen, topo, addr_type, input_dict_3, dut="r5", peer="r1", expected=False - ) - assert ( - result is not True - ), "Testcase {} : Failed \n " "r5: EOR is set to TRUE\n Error: {}".format( - tc_name, result - ) - logger.info(" Expected behavior: {}".format(result)) - - # Verifying BGP RIB routes after starting BGPd daemon - input_dict_1 = {key: topo["routers"][key] for key in ["r5"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False) - assert result is not True, ( - "Testcase {} : Failed \n " - "r3: routes are still present in BGP RIB\n Error: {}".format( - tc_name, result - ) - ) - logger.info(" Expected behavior: {}".format(result)) - - # Verifying RIB routes - result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False) - assert result is not True, ( - "Testcase {} : Failed \n " - "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) - ) - logger.info(" Expected behavior: {}".format(result)) - - write_test_footer(tc_name) - - -def test_BGP_GR_chaos_37_p1(request): - """ - Test Objective : Verify if helper node restarts before sending the - EOR message, restarting node doesn't wait until stale path timer - expiry to do the best path selection and sends an EOR - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - " Test Case : test_BGP_GR_chaos_37 " - "BGP GR " - "[Restart Mode]R1---R3[Helper Mode]" - ) - - logger.info( - "[Step 1] : Configure restarting router R3 to prevent " "sending an EOR.." - ) - - logger.info("[Step 2] : Reset the session between R3 and R1..") - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - } - } - }, - "r3": { - "bgp": { - "graceful-restart": {"disable-eor": True}, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - }, - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r3" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verify EOR is disabled - result = verify_eor( - tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False - ) - assert ( - result is not True - ), "Testcase {} : Failed \n " "r3: EOR is set to True\n Error: {}".format( - tc_name, result - ) - logger.info(" Expected behavior: {}".format(result)) - - # Verifying BGP RIB routes after starting BGPd daemon - dut = "r1" - input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("[Step 3] : Kill BGPd daemon on R1..") - - # Kill BGPd daemon on R1 - kill_router_daemons(tgen, "r1", ["bgpd"]) - - logger.info("[Step 4] : Start BGPd daemon on R1..") - - # Start BGPd daemon on R1 - start_router_daemons(tgen, "r1", ["bgpd"]) - - logger.info("[Step 5] : Kill BGPd daemon on R3..") - - # Kill BGPd daemon on R3 - kill_router_daemons(tgen, "r3", ["bgpd"]) - - # Modify graceful-restart config to prevent sending EOR - input_dict_2 = {"r3": {"bgp": {"graceful-restart": {"disable-eor": True}}}} - - result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2) - assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result) - - logger.info("[Step 6] : Start BGPd daemon on R3..") - - # Start BGPd daemon on R3 - start_router_daemons(tgen, "r3", ["bgpd"]) - - for addr_type in ADDR_TYPES: - # Verify r_bit - result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r3") - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes - input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verify EOR is send from R1 to R3 - input_dict_3 = {"r1": {"bgp": {"graceful-restart": {"disable-eor": True}}}} - - result = verify_eor( - tgen, topo, addr_type, input_dict_3, dut="r1", peer="r3", expected=False - ) - assert ( - result is not True - ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format( - tc_name, result - ) - - write_test_footer(tc_name) - - -def test_BGP_GR_chaos_30_p1(request): - """ - Test Objective : Restarting node removes stale routes from Zebra - after receiving an EOR from helper router. - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - " Test Case : test_BGP_GR_chaos_30 " - "BGP GR [Helper Mode]R3-----R1[Restart Mode] " - ) - - # Configure graceful-restart and timers - input_dict = { - "r1": { - "bgp": { - "graceful-restart": {"preserve-fw-state": True}, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - }, - } - }, - "r3": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r3" - ) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes before shutting down BGPd daemon - dut = "r1" - input_dict = {key: topo["routers"][key] for key in ["r3"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict) - assert result is True, "Testcase {} : Failed \n Error {}".format( - tc_name, result - ) - - logger.info("[Step 2] : Kill BGPd daemon on R1..") - - # Kill BGPd daemon on R1 - kill_router_daemons(tgen, "r1", ["bgpd"]) - - logger.info("[Step 3] : Withdraw advertised prefixes from R3...") - - # Api call to delete advertised networks - network = {"ipv4": "103.0.20.1/32", "ipv6": "3::1/128"} - for addr_type in ADDR_TYPES: - input_dict = { - "r3": { - "bgp": { - "address_family": { - addr_type: { - "unicast": { - "advertise_networks": [ - { - "network": network[addr_type], - "no_of_network": 5, - "delete": True, - } - ] - } - } - } - } - } - } - - result = create_router_bgp(tgen, topo, input_dict) - assert result is True, "Testcase {} : Failed \n Error: {}".format( - tc_name, result - ) - - logger.info("[Step 4] : Start BGPd daemon on R1..") - - # Start BGPd daemon on R1 - start_router_daemons(tgen, "r1", ["bgpd"]) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes before shutting down BGPd daemon - input_dict = {key: topo["routers"][key] for key in ["r3"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False) - assert result is not True, ( - "Testcase {} : Failed \n " - "r1: routes are still present in BGP RIB\n Error: {}".format( - tc_name, result - ) - ) - logger.info(" Expected behavior: {}".format(result)) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict, expected=False) - assert result is not True, ( - "Testcase {} : Failed \n " - "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) - ) - logger.info(" Expected behavior: {}".format(result)) - - write_test_footer(tc_name) - - -def test_BGP_GR_15_p2(request): - """ - Test Objective : Test GR scenarios by enabling Graceful Restart - for multiple address families.. - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r6": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r6": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - } - } - }, - "r6": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r6": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r6": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r6" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - logger.info( - "[Step 2] : Test Setup " - "[Helper Mode]R6-----R1[Restart Mode]" - "--------R2[Helper Mode] Initilized" - ) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - } - } - }, - "r2": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r2": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r2": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes - dut = "r6" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes - dut = "r6" - input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Kill BGPd daemon on R1 - kill_router_daemons(tgen, "r1", ["bgpd"]) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes - dut = "r6" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes - dut = "r6" - input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Start BGPd daemon on R1 - start_router_daemons(tgen, "r1", ["bgpd"]) - - for addr_type in ADDR_TYPES: - result = verify_bgp_convergence(tgen, topo) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes - dut = "r6" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes - dut = "r6" - input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - write_test_footer(tc_name) - - -def BGP_GR_TC_7_p1(request): - """ - Verify that BGP restarting node deletes all the routes received from peer - if BGP Graceful capability is not present in BGP Open message from the - peer - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - " Verify route download to RIB: BGP_GR_TC_7 >> " - "BGP GR [Helper Mode]R3-----R1[Restart Mode] " - ) - - # Configure graceful-restart - input_dict = { - "r3": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - "r1": { - "bgp": { - "graceful-restart": { - "graceful-restart": True, - "preserve-fw-state": True, - }, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r3": {"dest_link": {"r1": {"graceful-restart": True}}} - } - } - }, - }, - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r3" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes received from router R1 - dut = "r1" - input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - logger.info("R1 goes for reload") - kill_router_daemons(tgen, "r1", ["bgpd"]) - - # Change the configuration on router R1 - input_dict_2 = { - "r3": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-disable": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-disable": True} - } - } - } - } - }, - } - } - } - } - - result = create_router_bgp(tgen, topo, input_dict_2) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - # Change the configuration on R1 - network = {"ipv4": "103.0.20.1/32", "ipv6": "3::1/128"} - for addr_type in ADDR_TYPES: - input_dict_2 = { - "r3": { - "bgp": { - "address_family": { - addr_type: { - "unicast": { - "advertise_networks": [ - { - "network": network[addr_type], - "no_of_network": 5, - "delete": True, - } - ] - } - } - } - } - } - } - - result = create_router_bgp(tgen, topo, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - logger.info("R1 is about to come up now") - start_router_daemons(tgen, "r1", ["bgpd"]) - logger.info("R1 is UP Now") - - # Wait for RIB stale timeout - logger.info("Verify routes are not present" "in restart router") - - for addr_type in ADDR_TYPES: - # Verifying RIB routes - dut = "r1" - input_dict_1 = {key: topo["routers"][key] for key in ["r3"]} - result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False) - assert result is not True, ( - "Testcase {} : Failed \n " - "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) - ) - - write_test_footer(tc_name) - - -def test_BGP_GR_TC_23_p1(request): - """ - Verify that helper routers are deleting stale routes after stale route - timer's expiry. If all the routes are not received from restating node - after restart. - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - "Verify Stale Routes are deleted on helper: BGP_GR_TC_23 >> " - "BGP GR [Helper Mode]R1-----R2[Restart Mode] " - ) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "graceful-restart": {"timer": {"stalepath-time": GR_STALEPATH_TIMER}}, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1": {"graceful-restart-helper": True} - } - } - } - } - }, - }, - } - }, - "r2": { - "bgp": { - "graceful-restart": { - "graceful-restart": True, - "preserve-fw-state": True, - }, - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": {"dest_link": {"r2": {"graceful-restart": True}}} - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": {"dest_link": {"r2": {"graceful-restart": True}}} - } - } - }, - }, - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes received from router R1 - dut = "r1" - input_dict_1 = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - logger.info("R2 goes for reload") - kill_router_daemons(tgen, "r2", ["bgpd"]) - - # Modify configuration to delete routes and include disable-eor - input_dict_3 = {"r2": {"bgp": {"graceful-restart": {"disable-eor": True}}}} - - result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3) - - # Modify configuration to delete routes and include disable-eor - network = {"ipv4": "102.0.20.1/32", "ipv6": "2::1/128"} - for addr_type in ADDR_TYPES: - input_dict_3 = { - "r2": { - "bgp": { - "address_family": { - addr_type: { - "unicast": { - "advertise_networks": [ - { - "network": network[addr_type], - "no_of_network": 3, - "delete": True, - } - ] - } - } - } - } - } - } - - result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - logger.info("BGPd comes up for r2") - start_router_daemons(tgen, "r2", ["bgpd"]) - - # Wait for stalepath timer - logger.info("Waiting for stalepath timer({} sec..)".format(GR_STALEPATH_TIMER)) - sleep(GR_STALEPATH_TIMER) - - for addr_type in ADDR_TYPES: - clear_bgp(tgen, addr_type, "r2") - - # Verifying RIB routes - dut = "r1" - network = {"ipv4": "102.0.20.4/32", "ipv6": "2::4/128"} - for addr_type in ADDR_TYPES: - input_dict_1 = { - "r1": { - "bgp": { - "address_family": { - addr_type: { - "unicast": { - "advertise_networks": [ - {"network": network[addr_type], "no_of_network": 2} - ] - } - } - } - } - } - } - - # Verify EOR on helper router - result = verify_eor( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False - ) - assert ( - result is not True - ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format( - tc_name, result - ) - - # Verifying BGP RIB routes received from router R1 - dut = "r1" - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - write_test_footer(tc_name) - - -def test_BGP_GR_20_p1(request): - """ - Test Objective : Verify that GR routers delete all the routes - received from a node if both the routers are configured as GR - helper node - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - "[Step 1] : Test Setup " "[Restart Mode]R3-----R1[Restart Mode] Initilized" - ) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r3": { - "dest_link": { - "r1": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r3": { - "dest_link": { - "r1": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - "r3": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r3" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes - dut = "r3" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Kill BGPd daemon on R1 - kill_router_daemons(tgen, "r1", ["bgpd"]) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes - dut = "r3" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False) - assert result is not True, ( - "Testcase {} : Failed \n " - "r3: routes are still present in BGP RIB\n Error: {}".format( - tc_name, result - ) - ) - logger.info(" Expected behavior: {}".format(result)) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False) - assert result is not True, ( - "Testcase {} : Failed \n " - "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result) - ) - logger.info(" Expected behavior: {}".format(result)) - - # Start BGPd daemon on R1 - start_router_daemons(tgen, "r1", ["bgpd"]) - - for addr_type in ADDR_TYPES: - result = verify_bgp_convergence(tgen, topo) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes - dut = "r3" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - write_test_footer(tc_name) - - -def test_BGP_GR_21_p2(request): - """ - Test Objective : VVerify BGP-GR feature when helper node is - a transit router for it's eBGP peers. - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - "[Step 1] : Test Setup " "[Helper Mode]R6-----R1[Restart Mode] Initilized" - ) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r6": { - "dest_link": { - "r1": {"graceful-restart-disable": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r6": { - "dest_link": { - "r1": {"graceful-restart-disable": True} - } - } - } - } - }, - } - } - }, - "r6": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r6": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r6": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r6" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - logger.info( - "[Step 2] : Test Setup " - "[Restart Mode]R2-----[Helper Mode]R1[Disable Mode]" - "--------R6[Helper Mode] Initilized" - ) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - "r2": { - "bgp": { - "graceful-restart": { - "graceful-restart": True, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes - dut = "r6" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes - dut = "r6" - input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Kill BGPd daemon on R1 - kill_router_daemons(tgen, "r2", ["bgpd"]) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes - dut = "r6" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes - dut = "r6" - input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Start BGPd daemon on R1 - start_router_daemons(tgen, "r2", ["bgpd"]) - - for addr_type in ADDR_TYPES: - result = verify_bgp_convergence(tgen, topo) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes - dut = "r6" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes after bringing up BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes - dut = "r6" - input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - write_test_footer(tc_name) - - -def test_BGP_GR_22_p2(request): - """ - Test Objective : Verify BGP-GR feature when helper node - is a transit router for it's iBGP peers. - """ - - tgen = get_topogen() - tc_name = request.node.name - write_test_header(tc_name) - - # Check router status - check_router_status(tgen) - - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Creating configuration from JSON - reset_config_on_routers(tgen) - - logger.info( - "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] Initilized" - ) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r3": { - "dest_link": { - "r1": { - "graceful-restart-disable": True, - "next_hop_self": True, - } - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r3": { - "dest_link": { - "r1": { - "graceful-restart-disable": True, - "next_hop_self": True, - } - } - } - } - } - }, - } - } - }, - "r3": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r1": { - "dest_link": { - "r3": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r3" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - logger.info( - "[Step 2] : Test Setup " - "[Restart Mode]R2-----[Helper Mode]R1[Disable Mode]" - "--------R3[Helper Mode] Initilized" - ) - - # Configure graceful-restart - input_dict = { - "r1": { - "bgp": { - "address_family": { - "ipv4": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1": {"graceful-restart-helper": True} - } - } - } - } - }, - "ipv6": { - "unicast": { - "neighbor": { - "r2": { - "dest_link": { - "r1": {"graceful-restart-helper": True} - } - } - } - } - }, - } - } - }, - "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}, - } - - configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2") - - for addr_type in ADDR_TYPES: - result = verify_graceful_restart( - tgen, topo, addr_type, input_dict, dut="r1", peer="r2" - ) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes - dut = "r3" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes - dut = "r3" - input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Kill BGPd daemon on R1 - kill_router_daemons(tgen, "r2", ["bgpd"]) - - for addr_type in ADDR_TYPES: - # Verifying BGP RIB routes - dut = "r3" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes - dut = "r3" - input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Start BGPd daemon on R1 - start_router_daemons(tgen, "r2", ["bgpd"]) - - for addr_type in ADDR_TYPES: - result = verify_bgp_convergence(tgen, topo) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes - dut = "r3" - input_dict_1 = {key: topo["routers"][key] for key in ["r1"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_1) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying BGP RIB routes - dut = "r3" - input_dict_2 = {key: topo["routers"][key] for key in ["r2"]} - result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - # Verifying RIB routes before shutting down BGPd daemon - result = verify_rib(tgen, addr_type, dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) - - write_test_footer(tc_name) - - -if __name__ == "__main__": - args = ["-s"] + sys.argv[1:] - sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py index c1a9499cbe..25951281a7 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py @@ -294,16 +294,16 @@ luCommand( "1 available, best", "wait", "Ensure 99.0.0.4 shows up", - 10 - ) + 10, +) luCommand( "r1", 'vtysh -c "show bgp vrf r1-cust1 ipv4 uni 5.1.0.0/24"', "2 available, best", "wait", "Ensure 5.1.0.0 shows up", - 10 - ) + 10, +) want_r1_remote_cust1_routes = [ {"p": "5.1.0.0/24", "n": "3.3.3.3", "bp": False}, {"p": "5.1.0.0/24", "n": "99.0.0.1", "bp": True}, @@ -316,9 +316,9 @@ want_r1_remote_cust1_routes = [ {"p": "6.0.1.0/24", "n": "3.3.3.3", "bp": False}, {"p": "6.0.1.0/24", "n": "4.4.4.4", "bp": False}, {"p": "6.0.1.0/24", "n": "99.0.0.1", "bp": True}, - {"p": "6.0.2.0/24", "n": "3.3.3.3", "bp": False}, + {"p": "6.0.2.0/24", "n": "3.3.3.3", "bp": True}, {"p": "6.0.2.0/24", "n": "4.4.4.4", "bp": False}, - {"p": "6.0.2.0/24", "n": "99.0.0.1", "bp": True}, + {"p": "6.0.2.0/24", "n": "99.0.0.1", "bp": False}, {"p": "99.0.0.1/32", "n": "192.168.1.2", "bp": True}, {"p": "99.0.0.2/32", "n": "3.3.3.3"}, {"p": "99.0.0.3/32", "n": "4.4.4.4"}, @@ -338,16 +338,16 @@ luCommand( "1 available, best", "wait", "Ensure 99.0.0.4 shows up", - 10 - ) + 10, +) luCommand( "r3", 'vtysh -c "show bgp vrf r3-cust1 ipv4 uni 5.1.0.0/24"', "2 available, best", "wait", "Ensure 5.1.0.0 shows up", - 10 - ) + 10, +) want_r3_remote_cust1_routes = [ {"p": "5.1.0.0/24", "n": "1.1.1.1", "bp": True}, {"p": "5.1.0.0/24", "n": "99.0.0.2", "bp": False}, @@ -360,9 +360,9 @@ want_r3_remote_cust1_routes = [ {"p": "6.0.1.0/24", "n": "1.1.1.1", "bp": True}, {"p": "6.0.1.0/24", "n": "4.4.4.4", "bp": False}, {"p": "6.0.1.0/24", "n": "99.0.0.2", "bp": False}, - {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": False}, + {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": True}, {"p": "6.0.2.0/24", "n": "4.4.4.4", "bp": False}, - {"p": "6.0.2.0/24", "n": "99.0.0.2", "bp": True}, + {"p": "6.0.2.0/24", "n": "99.0.0.2", "bp": False}, {"p": "99.0.0.1/32", "n": "1.1.1.1", "bp": True}, {"p": "99.0.0.3/32", "n": "4.4.4.4", "bp": True}, {"p": "99.0.0.4/32", "n": "4.4.4.4", "bp": True}, @@ -382,24 +382,24 @@ luCommand( "1 available, best", "wait", "Ensure 99.0.0.4 shows up", - 10 - ) + 10, +) luCommand( "r4", 'vtysh -c "show bgp vrf r4-cust1 ipv4 uni 5.1.0.0/24"', "2 available, best", "wait", "Ensure 5.1.0.0 shows up", - 10 - ) + 10, +) luCommand( "r4", 'vtysh -c "show bgp vrf r4-cust1 ipv4 uni 99.0.0.2/32"', "1 available, best", "wait", "Ensure 99.0.0.2 shows up", - 10 - ) + 10, +) want_r4_remote_cust1_routes = [ {"p": "5.1.0.0/24", "n": "1.1.1.1", "bp": True}, {"p": "5.1.0.0/24", "n": "3.3.3.3", "bp": False}, @@ -409,10 +409,10 @@ want_r4_remote_cust1_routes = [ {"p": "6.0.1.0/24", "n": "3.3.3.3", "bp": False}, {"p": "6.0.1.0/24", "n": "99.0.0.3", "bp": False}, {"p": "6.0.1.0/24", "n": "99.0.0.4", "bp": False}, - {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": False}, + {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": True}, {"p": "6.0.2.0/24", "n": "3.3.3.3", "bp": False}, {"p": "6.0.2.0/24", "n": "99.0.0.3", "bp": False}, - {"p": "6.0.2.0/24", "n": "99.0.0.4", "bp": True}, + {"p": "6.0.2.0/24", "n": "99.0.0.4", "bp": False}, {"p": "99.0.0.1/32", "n": "1.1.1.1", "bp": True}, {"p": "99.0.0.2/32", "n": "3.3.3.3", "bp": True}, {"p": "99.0.0.3/32", "n": "192.168.1.2", "bp": True}, @@ -436,9 +436,9 @@ want_r4_remote_cust2_routes = [ {"p": "6.0.1.0/24", "n": "3.3.3.3", "bp": False}, {"p": "6.0.1.0/24", "n": "99.0.0.3", "bp": False}, {"p": "6.0.1.0/24", "n": "99.0.0.4", "bp": False}, - {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": False}, + {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": True}, {"p": "6.0.2.0/24", "n": "3.3.3.3", "bp": False}, - {"p": "6.0.2.0/24", "n": "99.0.0.3", "bp": True}, + {"p": "6.0.2.0/24", "n": "99.0.0.3", "bp": False}, {"p": "6.0.2.0/24", "n": "99.0.0.4", "bp": False}, {"p": "99.0.0.1/32", "n": "1.1.1.1", "bp": True}, {"p": "99.0.0.2/32", "n": "3.3.3.3", "bp": True}, @@ -632,8 +632,8 @@ luCommand( luCommand( "ce1", 'vtysh -c "show bgp ipv4 uni 6.0.2.0"', - "1 available, best .*192.168.1.1.* Local.* 99.0.0.1 from 0.0.0.0 .99.0.0.1" - + ".* Origin IGP, metric 100, localpref 100, weight 32768, valid, sourced, local, best .First path received" + "2 available, best .*192.168.1.1.* Local.* 99.0.0.1 from 0.0.0.0 .99.0.0.1" + + ".* Origin IGP, metric 100, localpref 100, weight 32768, valid, sourced, local, best .Weight" + ".* Community: 0:67.* Extended Community: RT:89:123.* Large Community: 12:34:11", "pass", "Redundant route 2 details", @@ -641,8 +641,8 @@ luCommand( luCommand( "ce2", 'vtysh -c "show bgp ipv4 uni 6.0.2.0"', - "1 available, best .*192.168.1.1.* Local.* 99.0.0.2 from 0.0.0.0 .99.0.0.2" - + ".* Origin IGP, metric 100, localpref 100, weight 32768, valid, sourced, local, best .First path received" + "2 available, best .*192.168.1.1.* Local.* 99.0.0.2 from 0.0.0.0 .99.0.0.2" + + ".* Origin IGP, metric 100, localpref 100, weight 32768, valid, sourced, local, best .Weight" + ".* Community: 0:67.* Extended Community: RT:89:123.* Large Community: 12:34:12", "pass", "Redundant route 2 details", @@ -661,7 +661,7 @@ luCommand( 'vtysh -c "show bgp ipv4 uni 6.0.2.0"', "2 available, best .*192.168.1.1.* Local.* 192.168.1.1 from 192.168.1.1 .192.168.1.1" + ".* Origin IGP, metric 100, localpref 100, valid, internal" - + ".* Community: 0:67.* Extended Community: RT:52:100 RT:89:123.* Large Community: 12:34:14", + + ".* Community: 0:67.* Extended Community: RT:52:100 RT:89:123.* Large Community: 12:34:11", "pass", "Redundant route 2 details", ) @@ -670,7 +670,7 @@ luCommand( 'vtysh -c "show bgp vrf ce4-cust2 ipv4 6.0.2.0"', "2 available, best .*192.168.2.1.* Local.* 192.168.2.1 from 192.168.2.1 .192.168.2.1" + ".* Origin IGP, metric 100, localpref 100, valid, internal" - + ".* Community: 0:67.* Extended Community: RT:52:100 RT:89:123.* Large Community: 12:34:13", + + ".* Community: 0:67.* Extended Community: RT:52:100 RT:89:123.* Large Community: 12:34:11", "pass", "Redundant route 2 details", ) diff --git a/tests/topotests/bgp_multiview_topo1/peer1/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer1/exa-send.py index fbb73f5b6a..09f6ea59e5 100755 --- a/tests/topotests/bgp_multiview_topo1/peer1/exa-send.py +++ b/tests/topotests/bgp_multiview_topo1/peer1/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_multiview_topo1/peer2/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer2/exa-send.py index fbb73f5b6a..09f6ea59e5 100755 --- a/tests/topotests/bgp_multiview_topo1/peer2/exa-send.py +++ b/tests/topotests/bgp_multiview_topo1/peer2/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_multiview_topo1/peer3/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer3/exa-send.py index fbb73f5b6a..09f6ea59e5 100755 --- a/tests/topotests/bgp_multiview_topo1/peer3/exa-send.py +++ b/tests/topotests/bgp_multiview_topo1/peer3/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_multiview_topo1/peer4/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer4/exa-send.py index fbb73f5b6a..09f6ea59e5 100755 --- a/tests/topotests/bgp_multiview_topo1/peer4/exa-send.py +++ b/tests/topotests/bgp_multiview_topo1/peer4/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_multiview_topo1/peer5/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer5/exa-send.py index fbb73f5b6a..09f6ea59e5 100755 --- a/tests/topotests/bgp_multiview_topo1/peer5/exa-send.py +++ b/tests/topotests/bgp_multiview_topo1/peer5/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_multiview_topo1/peer6/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer6/exa-send.py index fbb73f5b6a..09f6ea59e5 100755 --- a/tests/topotests/bgp_multiview_topo1/peer6/exa-send.py +++ b/tests/topotests/bgp_multiview_topo1/peer6/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_multiview_topo1/peer7/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer7/exa-send.py index fbb73f5b6a..09f6ea59e5 100755 --- a/tests/topotests/bgp_multiview_topo1/peer7/exa-send.py +++ b/tests/topotests/bgp_multiview_topo1/peer7/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_multiview_topo1/peer8/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer8/exa-send.py index fbb73f5b6a..09f6ea59e5 100755 --- a/tests/topotests/bgp_multiview_topo1/peer8/exa-send.py +++ b/tests/topotests/bgp_multiview_topo1/peer8/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/bgp_peer_type_multipath_relax/peer1/exa_readpipe.py b/tests/topotests/bgp_peer_type_multipath_relax/peer1/exa_readpipe.py index 9e689a27e3..0f998c1613 100644 --- a/tests/topotests/bgp_peer_type_multipath_relax/peer1/exa_readpipe.py +++ b/tests/topotests/bgp_peer_type_multipath_relax/peer1/exa_readpipe.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 "Helper script to read api commands from a pipe and feed them to ExaBGP" import sys diff --git a/tests/topotests/bgp_peer_type_multipath_relax/peer2/exa_readpipe.py b/tests/topotests/bgp_peer_type_multipath_relax/peer2/exa_readpipe.py index 9e689a27e3..0f998c1613 100644 --- a/tests/topotests/bgp_peer_type_multipath_relax/peer2/exa_readpipe.py +++ b/tests/topotests/bgp_peer_type_multipath_relax/peer2/exa_readpipe.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 "Helper script to read api commands from a pipe and feed them to ExaBGP" import sys diff --git a/tests/topotests/bgp_peer_type_multipath_relax/peer3/exa_readpipe.py b/tests/topotests/bgp_peer_type_multipath_relax/peer3/exa_readpipe.py index 9e689a27e3..0f998c1613 100644 --- a/tests/topotests/bgp_peer_type_multipath_relax/peer3/exa_readpipe.py +++ b/tests/topotests/bgp_peer_type_multipath_relax/peer3/exa_readpipe.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 "Helper script to read api commands from a pipe and feed them to ExaBGP" import sys diff --git a/tests/topotests/bgp_peer_type_multipath_relax/peer4/exa_readpipe.py b/tests/topotests/bgp_peer_type_multipath_relax/peer4/exa_readpipe.py index 9e689a27e3..0f998c1613 100644 --- a/tests/topotests/bgp_peer_type_multipath_relax/peer4/exa_readpipe.py +++ b/tests/topotests/bgp_peer_type_multipath_relax/peer4/exa_readpipe.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 "Helper script to read api commands from a pipe and feed them to ExaBGP" import sys diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/__init__.py b/tests/topotests/bgp_route_map_match_ipv6_nexthop/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/__init__.py diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/bgpd.conf b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/bgpd.conf new file mode 100644 index 0000000000..c2a49252d6 --- /dev/null +++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/bgpd.conf @@ -0,0 +1,32 @@ +! +ipv6 access-list nh1 permit 2001:db8:1::/64 +ipv6 access-list nh2 permit 2001:db8:2::/64 +ipv6 access-list nh3 permit 2001:db8:3::/64 +! +ipv6 prefix-list nh4 permit 2001:db8:5::/64 le 128 +! +router bgp 65001 + bgp router-id 10.10.10.1 + no bgp ebgp-requires-policy + neighbor 2001:db8::2 remote-as external + address-family ipv6 unicast + neighbor 2001:db8::2 activate + neighbor 2001:db8::2 route-map r2 in + exit-address-family +! +route-map r2 permit 10 + match ipv6 next-hop nh1 + set community 65002:1 +route-map r2 permit 20 + match ipv6 next-hop nh2 + set community 65002:2 +route-map r2 permit 30 + match ipv6 next-hop nh3 + set community 65002:3 +route-map r2 permit 40 + match ipv6 next-hop address 2001:db8:4::1 + set community 65002:4 +route-map r2 permit 50 + match ipv6 next-hop prefix-list nh4 + set community 65002:5 +! diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/zebra.conf b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/zebra.conf new file mode 100644 index 0000000000..1d4374bd8f --- /dev/null +++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/zebra.conf @@ -0,0 +1,4 @@ +! +int r1-eth0 + ipv6 address 2001:db8::1/64 +! diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/bgpd.conf b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/bgpd.conf new file mode 100644 index 0000000000..19dcf3664b --- /dev/null +++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/bgpd.conf @@ -0,0 +1,33 @@ +! +router bgp 65002 + bgp router-id 10.10.10.2 + no bgp ebgp-requires-policy + neighbor 2001:db8::1 remote-as external + address-family ipv6 unicast + redistribute connected + neighbor 2001:db8::1 activate + neighbor 2001:db8::1 route-map r1 out + exit-address-family +! +ipv6 prefix-list p1 permit 2001:db8:1::1/128 +ipv6 prefix-list p2 permit 2001:db8:2::1/128 +ipv6 prefix-list p3 permit 2001:db8:3::1/128 +ipv6 prefix-list p4 permit 2001:db8:4::1/128 +ipv6 prefix-list p5 permit 2001:db8:5::1/128 +! +route-map r1 permit 10 + match ipv6 address prefix-list p1 + set ipv6 next-hop global 2001:db8:1::1 +route-map r1 permit 20 + match ipv6 address prefix-list p2 + set ipv6 next-hop global 2001:db8:2::1 +route-map r1 permit 30 + match ipv6 address prefix-list p3 + set ipv6 next-hop global 2001:db8:3::1 +route-map r1 permit 40 + match ipv6 address prefix-list p4 + set ipv6 next-hop global 2001:db8:4::1 +route-map r1 permit 50 + match ipv6 address prefix-list p5 + set ipv6 next-hop global 2001:db8:5::1 +! diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/zebra.conf b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/zebra.conf new file mode 100644 index 0000000000..e69345f4f6 --- /dev/null +++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/zebra.conf @@ -0,0 +1,11 @@ +! +int lo + ipv6 address 2001:db8:1::1/128 + ipv6 address 2001:db8:2::1/128 + ipv6 address 2001:db8:3::1/128 + ipv6 address 2001:db8:4::1/128 + ipv6 address 2001:db8:5::1/128 +! +int r2-eth0 + ip address 2001:db8::2/64 +! diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py b/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py new file mode 100644 index 0000000000..8c86526bf1 --- /dev/null +++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python + +# Copyright (c) 2021 by +# Donatas Abraitis <donatas.abraitis@gmail.com> +# +# 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 if we can match BGP prefixes by next-hop which is +specified by an IPv6 Access-list, prefix-list or just an address. +""" + +import os +import sys +import json +import pytest +import functools + +pytestmark = pytest.mark.bgpd + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen + +pytestmark = [pytest.mark.bgpd] + + +def build_topo(tgen): + for routern in range(1, 3): + tgen.add_router("r{}".format(routern)) + + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + + +def setup_module(mod): + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + for i, (rname, router) in enumerate(router_list.items(), 1): + 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() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_bgp_route_map_match_ipv6_next_hop_access_list(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + router = tgen.gears["r1"] + + def _bgp_converge(router): + output = json.loads(router.vtysh_cmd("show ipv6 route json")) + expected = { + "2001:db8:1::1/128": [ + { + "communities": "65002:1", + } + ], + "2001:db8:2::1/128": [ + { + "communities": "65002:2", + } + ], + "2001:db8:3::1/128": [ + { + "communities": "65002:3", + } + ], + "2001:db8:4::1/128": [ + { + "communities": "65002:4", + } + ], + "2001:db8:5::1/128": [ + { + "communities": "65002:5", + } + ], + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_converge, router) + success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assert result is None, "Can't match routes using ipv6 next-hop access-list" + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_route_server_client/__init__.py b/tests/topotests/bgp_route_server_client/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_route_server_client/__init__.py diff --git a/tests/topotests/bgp_route_server_client/r1/bgpd.conf b/tests/topotests/bgp_route_server_client/r1/bgpd.conf new file mode 100644 index 0000000000..9826b671f9 --- /dev/null +++ b/tests/topotests/bgp_route_server_client/r1/bgpd.conf @@ -0,0 +1,12 @@ +! +router bgp 65001 + bgp router-id 10.10.10.1 + no bgp ebgp-requires-policy + neighbor 2001:db8:1::1 remote-as external + neighbor 2001:db8:1::1 timers 3 10 + neighbor 2001:db8:1::1 timers connect 5 + address-family ipv6 unicast + redistribute connected + neighbor 2001:db8:1::1 activate + exit-address-family +! diff --git a/tests/topotests/bgp_route_server_client/r1/zebra.conf b/tests/topotests/bgp_route_server_client/r1/zebra.conf new file mode 100644 index 0000000000..08d0be6220 --- /dev/null +++ b/tests/topotests/bgp_route_server_client/r1/zebra.conf @@ -0,0 +1,7 @@ +! +int lo + ipv6 address 2001:db8:f::1/128 +! +int r1-eth0 + ipv6 address 2001:db8:1::2/64 +! diff --git a/tests/topotests/bgp_route_server_client/r2/bgpd.conf b/tests/topotests/bgp_route_server_client/r2/bgpd.conf new file mode 100644 index 0000000000..3b0a24b8ba --- /dev/null +++ b/tests/topotests/bgp_route_server_client/r2/bgpd.conf @@ -0,0 +1,17 @@ +router bgp 65000 view RS + bgp router-id 10.10.10.2 + no bgp ebgp-requires-policy + neighbor 2001:db8:1::2 remote-as external + neighbor 2001:db8:1::2 timers 3 10 + neighbor 2001:db8:1::2 timers connect 5 + neighbor 2001:db8:3::2 remote-as external + neighbor 2001:db8:3::2 timers 3 10 + neighbor 2001:db8:3::2 timers connect 5 + address-family ipv6 unicast + redistribute connected + neighbor 2001:db8:1::2 activate + neighbor 2001:db8:3::2 activate + neighbor 2001:db8:1::2 route-server-client + neighbor 2001:db8:3::2 route-server-client + exit-address-family +! diff --git a/tests/topotests/bgp_route_server_client/r2/zebra.conf b/tests/topotests/bgp_route_server_client/r2/zebra.conf new file mode 100644 index 0000000000..806bc4fe32 --- /dev/null +++ b/tests/topotests/bgp_route_server_client/r2/zebra.conf @@ -0,0 +1,7 @@ +! +int r2-eth0 + ipv6 address 2001:db8:1::1/64 +! +int r2-eth1 + ipv6 address 2001:db8:3::1/64 +! diff --git a/tests/topotests/bgp_route_server_client/r3/bgpd.conf b/tests/topotests/bgp_route_server_client/r3/bgpd.conf new file mode 100644 index 0000000000..60a5ffc559 --- /dev/null +++ b/tests/topotests/bgp_route_server_client/r3/bgpd.conf @@ -0,0 +1,12 @@ +! +router bgp 65003 + bgp router-id 10.10.10.3 + no bgp ebgp-requires-policy + neighbor 2001:db8:3::1 remote-as external + neighbor 2001:db8:3::1 timers 3 10 + neighbor 2001:db8:3::1 timers connect 5 + address-family ipv6 unicast + redistribute connected + neighbor 2001:db8:3::1 activate + exit-address-family +! diff --git a/tests/topotests/bgp_route_server_client/r3/zebra.conf b/tests/topotests/bgp_route_server_client/r3/zebra.conf new file mode 100644 index 0000000000..b5511a437c --- /dev/null +++ b/tests/topotests/bgp_route_server_client/r3/zebra.conf @@ -0,0 +1,7 @@ +! +int lo + ipv6 address 2001:db8:f::3/128 +! +int r3-eth0 + ipv6 address 2001:db8:3::2/64 +! diff --git a/tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py b/tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py new file mode 100644 index 0000000000..21088f7008 --- /dev/null +++ b/tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python + +# Copyright (c) 2021 by +# Donatas Abraitis <donatas.abraitis@gmail.com> +# +# 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 if we send ONLY GUA address for route-server-client peers. +""" + +import os +import sys +import json +import pytest +import functools + +pytestmark = pytest.mark.bgpd + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen + +pytestmark = [pytest.mark.bgpd] + + +def build_topo(tgen): + 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): + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + for i, (rname, router) in enumerate(router_list.items(), 1): + 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() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_bgp_route_server_client(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r1 = tgen.gears["r1"] + r2 = tgen.gears["r2"] + + def _bgp_converge(router): + output = json.loads(router.vtysh_cmd("show bgp ipv6 unicast summary json")) + expected = {"peers": {"2001:db8:1::1": {"state": "Established", "pfxRcd": 2}}} + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_converge, r1) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assert result is None, "Cannot see BGP sessions to be up" + + def _bgp_prefix_received(router): + output = json.loads(router.vtysh_cmd("show bgp 2001:db8:f::3/128 json")) + expected = { + "prefix": "2001:db8:f::3/128", + "paths": [{"nexthops": [{"ip": "2001:db8:3::2"}]}], + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_prefix_received, r1) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assert result is None, "Cannot see BGP GUA next hop from r3 in r1" + + def _bgp_single_next_hop(router): + output = json.loads(router.vtysh_cmd("show bgp 2001:db8:f::3/128 json")) + return len(output["paths"][0]["nexthops"]) + + assert ( + _bgp_single_next_hop(r1) == 1 + ), "Not ONLY one Next Hop received for 2001:db8:f::3/128" + + def _bgp_gua_lla_next_hop(router): + output = json.loads(router.vtysh_cmd("show bgp view RS 2001:db8:f::3/128 json")) + expected = { + "prefix": "2001:db8:f::3/128", + "paths": [ + { + "nexthops": [ + { + "ip": "2001:db8:3::2", + "hostname": "r3", + "afi": "ipv6", + "scope": "global", + }, + {"hostname": "r3", "afi": "ipv6", "scope": "link-local"}, + ] + } + ], + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_gua_lla_next_hop, r2) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assert result is None, "Cannot see BGP LLA next hop from r3 in r2" + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo1.json b/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo1.json new file mode 100644 index 0000000000..b1d7d09db8 --- /dev/null +++ b/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo1.json @@ -0,0 +1,563 @@ +{ + "address_types": ["ipv4","ipv6"], + "ipv4base": "10.0.0.0", + "ipv4mask": 30, + "ipv6base": "fd00::", + "ipv6mask": 64, + "link_ip_start": { + "ipv4": "10.0.0.0", + "v4mask": 30, + "ipv6": "fd00::", + "v6mask": 64 + }, + "lo_prefix": { + "ipv4": "1.0.", + "v4mask": 32, + "ipv6": "2001:db8:f::", + "v6mask": 128 + }, + "routers": { + "r1": { + "links": { + "r2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "ISR"}, + "r3-link1": {"ipv4": "auto", "ipv6": "auto"}, + "r4-link1": {"ipv4": "auto", "ipv6": "auto"} + }, + "vrfs":[ + { + "name": "ISR", + "id": "1" + } + ], + "bgp": + [ + { + "local_as": "100", + "vrf": "ISR", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": { + "keepalivetimer": 1, + "holddowntimer": 3, + "next_hop_self": true + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": { + "keepalivetimer": 1, + "holddowntimer": 3, + "next_hop_self": true, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + }, + { + "local_as": "100", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1-link1": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1-link1": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + }, + { + "local_as": "100", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "r1-link1": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "r1-link1": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + } + ], + "static_routes":[ + { + "network": ["11.11.11.1/32", "11.11.11.11/32"], + "next_hop":"Null0", + "vrf": "ISR" + }, + { + "network": ["11:11::1/128", "11:11::11/128"], + "next_hop":"Null0", + "vrf": "ISR" + }, + { + "network": ["10.10.10.10/32", "10.10.10.100/32"], + "next_hop":"Null0" + }, + { + "network": ["10:10::10/128", "10:10::100/128"], + "next_hop":"Null0" + } + ], + "route_maps": { + "rmap_global": [{ + "action": "permit", + "set": { + "ipv6": { + "nexthop": "prefer-global" + } + } + }] + } + }, + "r2": { + "links": { + "r1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "ISR"}, + "r3-link1": {"ipv4": "auto", "ipv6": "auto"}, + "r4-link1": {"ipv4": "auto", "ipv6": "auto"} + }, + "vrfs":[ + { + "name": "ISR", + "id": "1" + } + ], + "bgp": + [ + { + "local_as": "100", + "vrf": "ISR", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": { + "keepalivetimer": 1, + "holddowntimer": 3, + "next_hop_self": true + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": { + "keepalivetimer": 1, + "holddowntimer": 3, + "next_hop_self": true, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + }, + { + "local_as": "100", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r2-link1": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r2-link1": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + }, + { + "local_as": "100", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "r2-link1": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "r2-link1": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + } + ], + "static_routes":[ + { + "network": ["22.22.22.2/32", "22.22.22.22/32"], + "next_hop":"Null0", + "vrf": "ISR" + }, + { + "network": ["22:22::2/128", "22:22::22/128"], + "next_hop":"Null0", + "vrf": "ISR" + }, + { + "network": ["20.20.20.20/32", "20.20.20.200/32"], + "next_hop":"Null0" + }, + { + "network": ["20:20::20/128", "20:20::200/128"], + "next_hop":"Null0" + } + ], + "route_maps": { + "rmap_global": [{ + "action": "permit", + "set": { + "ipv6": { + "nexthop": "prefer-global" + } + } + }] + } + }, + "r3": { + "links": { + "r1-link1": {"ipv4": "auto", "ipv6": "auto"}, + "r2-link1": {"ipv4": "auto", "ipv6": "auto"} + }, + "bgp": + [ + { + "local_as": "300", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3-link1": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3-link1": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + }, + { + "local_as": "300", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r3-link1": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r3-link1": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + } + ], + "static_routes":[ + { + "network": ["30.30.30.3/32", "30.30.30.30/32"], + "next_hop":"Null0" + }, + { + "network": ["30:30::3/128", "30:30::30/128"], + "next_hop":"Null0" + }, + { + "network": ["50.50.50.5/32", "50.50.50.50/32"], + "next_hop":"Null0" + }, + { + "network": ["50:50::5/128", "50:50::50/128"], + "next_hop":"Null0" + } + ], + "route_maps": { + "rmap_global": [{ + "action": "permit", + "set": { + "ipv6": { + "nexthop": "prefer-global" + } + } + }] + } + }, + "r4": { + "links": { + "r1-link1": {"ipv4": "auto", "ipv6": "auto"}, + "r2-link1": {"ipv4": "auto", "ipv6": "auto"} + }, + "bgp": + [ + { + "local_as": "400", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r4-link1": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r4-link1": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + }, + { + "local_as": "400", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r4-link1": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r4-link1": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + } + ], + "static_routes":[ + { + "network": ["40.40.40.4/32", "40.40.40.40/32"], + "next_hop":"Null0" + }, + { + "network": ["40:40::4/128", "40:40::40/128"], + "next_hop":"Null0" + }, + { + "network": ["50.50.50.5/32", "50.50.50.50/32"], + "next_hop":"Null0" + }, + { + "network": ["50:50::5/128", "50:50::50/128"], + "next_hop":"Null0" + } + ], + "route_maps": { + "rmap_global": [{ + "action": "permit", + "set": { + "ipv6": { + "nexthop": "prefer-global" + } + } + }] + } + } + } +} diff --git a/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo2.json b/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo2.json new file mode 100644 index 0000000000..0b13882176 --- /dev/null +++ b/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo2.json @@ -0,0 +1,1088 @@ +{ + "address_types": ["ipv4","ipv6"], + "ipv4base": "10.0.0.0", + "ipv4mask": 24, + "ipv6base": "fd00::", + "ipv6mask": 64, + "link_ip_start": { + "ipv4": "10.0.0.0", + "v4mask": 24, + "ipv6": "fd00::", + "v6mask": 64 + }, + "lo_prefix": { + "ipv4": "1.0.", + "v4mask": 32, + "ipv6": "2001:db8:f::", + "v6mask": 128 + }, + "routers": { + "r1": { + "links": { + "r3-link1": {"ipv4": "192.168.1.1/24", "ipv6": "fd00:0:0:1::1/120", "vrf": "RED"}, + "r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "r3-link3": {"ipv4": "192.168.1.1/24", "ipv6": "fd00:0:0:1::1/120", "vrf": "GREEN"}, + "r3-link4": {"ipv4": "auto", "ipv6": "auto"} + }, + "vrfs":[ + {"name": "RED", "id": "1"}, + {"name": "BLUE", "id": "2"}, + {"name": "GREEN", "id": "3"} + ], + "bgp": + [ + { + "local_as": "1", + "vrf": "RED", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1-link1": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1-link1": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + }, + { + "local_as": "1", + "vrf": "BLUE", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1-link2": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1-link2": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + }, + { + "local_as": "1", + "vrf": "GREEN", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1-link3": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1-link3": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + }, + { + "local_as": "1", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1-link4": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1-link4": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + } + ], + "route_maps": { + "rmap_global": [{ + "action": "permit", + "set": { + "ipv6": { + "nexthop": "prefer-global" + } + } + }] + } + }, + "r2": { + "links": { + "r3-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"}, + "r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "r3-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"}, + "r3-link4": {"ipv4": "auto", "ipv6": "auto"} + }, + "vrfs":[ + {"name": "RED", "id": "1"}, + {"name": "BLUE", "id": "2"}, + {"name": "GREEN", "id": "3"} + ], + "bgp": + [ + { + "local_as": "2", + "vrf": "RED", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r2-link1": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r2-link1": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + }, + { + "local_as": "2", + "vrf": "BLUE", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r2-link2": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r2-link2": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + }, + { + "local_as": "2", + "vrf": "GREEN", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r2-link3": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r2-link3": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + }, + { + "local_as": "2", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r2-link4": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r2-link4": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + } + ], + "route_maps": { + "rmap_global": [{ + "action": "permit", + "set": { + "ipv6": { + "nexthop": "prefer-global" + } + } + }] + } + }, + "r3": { + "links": { + "r1-link1": {"ipv4": "192.168.1.2/24", "ipv6": "fd00:0:0:1::2/120", "vrf": "RED"}, + "r1-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "r1-link3": {"ipv4": "192.168.1.2/24", "ipv6": "fd00:0:0:1::2/120", "vrf": "GREEN"}, + "r1-link4": {"ipv4": "auto", "ipv6": "auto"}, + "r2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"}, + "r2-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "r2-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"}, + "r2-link4": {"ipv4": "auto", "ipv6": "auto"}, + "r4-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"}, + "r4-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "r4-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"}, + "r4-link4": {"ipv4": "auto", "ipv6": "auto"}, + "r5-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"}, + "r5-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "r5-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"}, + "r5-link4": {"ipv4": "auto", "ipv6": "auto"} + }, + "vrfs":[ + {"name": "RED", "id": "1"}, + {"name": "BLUE", "id": "2"}, + {"name": "GREEN", "id": "3"} + ], + "bgp": + [ + { + "local_as": "3", + "vrf": "RED", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3-link1": {} + } + }, + "r2": { + "dest_link": { + "r3-link1": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + }, + "r4": { + "dest_link": { + "r3-link1": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + }, + "r5": { + "dest_link": { + "r3-link1": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3-link1": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + }, + "r2": { + "dest_link": { + "r3-link1": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + }, + "r4": { + "dest_link": { + "r3-link1": { + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + }, + "r5": { + "dest_link": { + "r3-link1": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + }, + { + "local_as": "3", + "vrf": "BLUE", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3-link2": {} + } + }, + "r2": { + "dest_link": { + "r3-link2": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + }, + "r4": { + "dest_link": { + "r3-link2": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + }, + "r5": { + "dest_link": { + "r3-link2": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3-link2": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + }, + "r2": { + "dest_link": { + "r3-link2": { + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + }, + "r4": { + "dest_link": { + "r3-link2": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + }, + "r5": { + "dest_link": { + "r3-link2": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + }, + { + "local_as": "3", + "vrf": "GREEN", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3-link3": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + }, + "r2": { + "dest_link": { + "r3-link3": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + }, + "r4": { + "dest_link": { + "r3-link3": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + }, + "r5": { + "dest_link": { + "r3-link3": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3-link3": { + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + }, + "r2": { + "dest_link": { + "r3-link3": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + }, + "r4": { + "dest_link": { + "r3-link3": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + }, + "r5": { + "dest_link": { + "r3-link3": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + }, + { + "local_as": "3", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3-link4": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + }, + "r2": { + "dest_link": { + "r3-link4": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + }, + "r4": { + "dest_link": { + "r3-link4": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + }, + "r5": { + "dest_link": { + "r3-link4": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3-link4": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + }, + "r2": { + "dest_link": { + "r3-link4": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + }, + "r4": { + "dest_link": { + "r3-link4": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + }, + "r5": { + "dest_link": { + "r3-link4": { + "keepalivetimer": 1, + "holddowntimer": 3, + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + } + } + } + } + } + } + ], + "route_maps": { + "rmap_global": [{ + "action": "permit", + "set": { + "ipv6": { + "nexthop": "prefer-global" + } + } + }] + } + }, + "r4": { + "links": { + "r3-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"}, + "r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "r3-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"}, + "r3-link4": {"ipv4": "auto", "ipv6": "auto"} + }, + "vrfs":[ + {"name": "RED", "id": "1"}, + {"name": "BLUE", "id": "2"}, + {"name": "GREEN", "id": "3"} + ], + "bgp": + [ + { + "local_as": "4", + "vrf": "RED", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r4-link1": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r4-link1": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + } + } + }, + { + "local_as": "4", + "vrf": "BLUE", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r4-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r4-link2": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + } + } + }, + { + "local_as": "4", + "vrf": "GREEN", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r4-link3": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r4-link3": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + } + } + }, + { + "local_as": "4", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r4-link4": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r4-link4": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + } + } + } + ] + }, + "r5": { + "links": { + "r3-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"}, + "r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "r3-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"}, + "r3-link4": {"ipv4": "auto", "ipv6": "auto"} + }, + "vrfs":[ + {"name": "RED", "id": "1"}, + {"name": "BLUE", "id": "2"}, + {"name": "GREEN", "id": "3"} + ], + "bgp": + [ + { + "local_as": "3", + "vrf": "RED", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r5-link1": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r5-link1": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + } + } + }, + { + "local_as": "3", + "vrf": "BLUE", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r5-link2": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r5-link2": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + } + } + }, + { + "local_as": "3", + "vrf": "GREEN", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r5-link3": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r5-link3": {} + } + } + } + } + } + } + }, + { + "local_as": "3", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r5-link4": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r5-link4": { + "keepalivetimer": 1, + "holddowntimer": 3 + } + } + } + } + } + } + } + } + ] + } + } +} diff --git a/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo1.py b/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo1.py new file mode 100644 index 0000000000..d9d4f4f8b2 --- /dev/null +++ b/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo1.py @@ -0,0 +1,916 @@ +#!/usr/bin/env python + +# +# Copyright (c) 2020 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, +# Inc. ("NetDEF") in this file. +# +# 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 VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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. +# + +""" +Following tests are covered to test BGP VRF Lite: + +1. Verify BGP best path selection algorithm works fine when +routes are imported from ISR to default vrf and vice versa. +""" + +import os +import sys +import time +import pytest +import platform + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) +sys.path.append(os.path.join(CWD, "../lib/")) + +# Required to instantiate the topology builder class. + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib.topogen import Topogen, get_topogen +from lib.topotest import version_cmp + +from lib.common_config import ( + start_topology, + write_test_header, + check_address_types, + write_test_footer, + step, + create_route_maps, + create_prefix_lists, + check_router_status, + get_frr_ipv6_linklocal, + shutdown_bringup_interface, +) + +from lib.topolog import logger +from lib.bgp import ( + verify_bgp_convergence, + create_router_bgp, + verify_bgp_community, + verify_bgp_rib, + clear_bgp, + verify_best_path_as_per_bgp_attribute +) +from lib.topojson import build_config_from_json + + +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + +# Global variables +NETWORK1_1 = {"ipv4": "11.11.11.1/32", "ipv6": "11:11::1/128"} +NETWORK1_2 = {"ipv4": "11.11.11.11/32", "ipv6": "11:11::11/128"} +NETWORK1_3 = {"ipv4": "10.10.10.10/32", "ipv6": "10:10::10/128"} +NETWORK1_4 = {"ipv4": "10.10.10.100/32", "ipv6": "10:10::100/128"} + +NETWORK2_1 = {"ipv4": "22.22.22.2/32", "ipv6": "22:22::2/128"} +NETWORK2_2 = {"ipv4": "22.22.22.22/32", "ipv6": "22:22::22/128"} +NETWORK2_3 = {"ipv4": "20.20.20.20/32", "ipv6": "20:20::20/128"} +NETWORK2_4 = {"ipv4": "20.20.20.200/32", "ipv6": "20:20::200/128"} + +NETWORK3_1 = {"ipv4": "30.30.30.3/32", "ipv6": "30:30::3/128"} +NETWORK3_2 = {"ipv4": "30.30.30.30/32", "ipv6": "30:30::30/128"} +NETWORK3_3 = {"ipv4": "50.50.50.5/32", "ipv6": "50:50::5/128"} +NETWORK3_4 = {"ipv4": "50.50.50.50/32", "ipv6": "50:50::50/128"} + +NETWORK4_1 = {"ipv4": "40.40.40.4/32", "ipv6": "40:40::4/128"} +NETWORK4_2 = {"ipv4": "40.40.40.40/32", "ipv6": "40:40::40/128"} +NETWORK4_3 = {"ipv4": "50.50.50.5/32", "ipv6": "50:50::5/128"} +NETWORK4_4 = {"ipv4": "50.50.50.50/32", "ipv6": "50:50::50/128"} +NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"} +LOOPBACK_1 = { + "ipv4": "10.0.0.7/24", + "ipv6": "fd00:0:0:1::7/64", + "ipv4_mask": "255.255.255.0", + "ipv6_mask": None, +} +LOOPBACK_2 = { + "ipv4": "10.0.0.16/24", + "ipv6": "fd00:0:0:3::5/64", + "ipv4_mask": "255.255.255.0", + "ipv6_mask": None, +} +PREFERRED_NEXT_HOP = "global" + + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + + testsuite_run_time = time.asctime(time.localtime(time.time())) + logger.info("Testsuite start time: {}".format(testsuite_run_time)) + logger.info("=" * 40) + + logger.info("Running setup_module to create topology") + + # This function initiates the topology build with Topogen... + json_file = "{}/bgp_vrf_lite_best_path_topo1.json".format(CWD) + tgen = Topogen(json_file, mod.__name__) + global topo + topo = tgen.json_topo + # ... and here it calls Mininet initialization functions. + + # Starting topology, create tmp files which are loaded to routers + # to start deamons and then start routers + start_topology(tgen) + + # Run these tests for kernel version 4.19 or above + if version_cmp(platform.release(), "4.19") < 0: + error_msg = ( + "BGP vrf dynamic route leak tests will not run " + '(have kernel "{}", but it requires >= 4.19)'.format(platform.release()) + ) + pytest.skip(error_msg) + + # Creating configuration from JSON + build_config_from_json(tgen, topo) + + global BGP_CONVERGENCE + global ADDR_TYPES + ADDR_TYPES = check_address_types() + + BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) + assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error: {}".format( + BGP_CONVERGENCE + ) + + logger.info("Running setup_module() done") + + +def teardown_module(): + """Teardown the pytest environment""" + + logger.info("Running teardown_module to delete topology") + + tgen = get_topogen() + + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + logger.info( + "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) + ) + logger.info("=" * 40) + + +##################################################### +# +# Testcases +# +##################################################### + + +def disable_route_map_to_prefer_global_next_hop(tgen, topo): + """ + This API is to remove prefer global route-map applied on neighbors + + Parameter: + ---------- + * `tgen` : Topogen object + * `topo` : Input JSON data + + Returns: + -------- + True/errormsg + + """ + + logger.info("Remove prefer-global rmap applied on neighbors") + input_dict = { + "r1": { + "bgp": [ + { + "local_as": "100", + "vrf": "ISR", + "address_family": { + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": { + "route_maps": [ + { + "name": "rmap_global", + "direction": "in", + "delete": True, + } + ] + } + } + } + } + } + } + }, + }, + { + "local_as": "100", + "address_family": { + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1-link1": { + "route_maps": [ + { + "name": "rmap_global", + "direction": "in", + "delete": True, + } + ] + } + } + } + } + } + } + }, + }, + { + "local_as": "100", + "address_family": { + "ipv6": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "r1-link1": { + "route_maps": [ + { + "name": "rmap_global", + "direction": "in", + "delete": True, + } + ] + } + } + } + } + } + } + }, + }, + ] + }, + "r2": { + "bgp": [ + { + "local_as": "100", + "vrf": "ISR", + "address_family": { + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": { + "route_maps": [ + { + "name": "rmap_global", + "direction": "in", + "delete": True, + } + ] + } + } + } + } + } + } + }, + }, + { + "local_as": "100", + "address_family": { + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r2-link1": { + "route_maps": [ + { + "name": "rmap_global", + "direction": "in", + "delete": True, + } + ] + } + } + } + } + } + } + }, + }, + { + "local_as": "100", + "address_family": { + "ipv6": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "r2-link1": { + "route_maps": [ + { + "name": "rmap_global", + "direction": "in", + "delete": True, + } + ] + } + } + } + } + } + } + }, + }, + ] + }, + "r3": { + "bgp": [ + { + "local_as": "300", + "address_family": { + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3-link1": { + "route_maps": [ + { + "name": "rmap_global", + "direction": "in", + "delete": True, + } + ] + } + } + } + } + } + } + }, + }, + { + "local_as": "300", + "address_family": { + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r3-link1": { + "route_maps": [ + { + "name": "rmap_global", + "direction": "in", + "delete": True, + } + ] + } + } + } + } + } + } + }, + }, + ] + }, + "r4": { + "bgp": [ + { + "local_as": "400", + "address_family": { + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r4-link1": { + "route_maps": [ + { + "name": "rmap_global", + "direction": "in", + "delete": True, + } + ] + } + } + } + } + } + } + }, + }, + { + "local_as": "400", + "address_family": { + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r4-link1": { + "route_maps": [ + { + "name": "rmap_global", + "direction": "in", + "delete": True, + } + ] + } + } + } + } + } + } + }, + }, + ] + }, + } + + result = create_router_bgp(tgen, topo, input_dict) + assert result is True, "Testcase :Failed \n Error: {}".format(result) + + return True + + +def test_bgp_best_path_with_dynamic_import_p0(request): + """ + 1.5.6. Verify BGP best path selection algorithm works fine when + routes are imported from ISR to default vrf and vice versa. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + build_config_from_json(tgen, topo) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + for addr_type in ADDR_TYPES: + + step( + "Redistribute configured static routes into BGP process" " on R1/R2 and R3" + ) + + input_dict_1 = {} + DUT = ["r1", "r2", "r3", "r4"] + VRFS = ["ISR", "ISR", "default", "default"] + AS_NUM = [100, 100, 300, 400] + + for dut, vrf, as_num in zip(DUT, VRFS, AS_NUM): + temp = {dut: {"bgp": []}} + input_dict_1.update(temp) + + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + addr_type: { + "unicast": {"redistribute": [{"redist_type": "static"}]} + } + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_1) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + + step("Import from default vrf into vrf ISR on R1 and R2 as below") + + input_dict_vrf = {} + DUT = ["r1", "r2"] + VRFS = ["ISR", "ISR"] + AS_NUM = [100, 100] + + for dut, vrf, as_num in zip(DUT, VRFS, AS_NUM): + temp = {dut: {"bgp": []}} + input_dict_vrf.update(temp) + + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + addr_type: {"unicast": {"import": {"vrf": "default"}}} + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_vrf) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + input_dict_default = {} + DUT = ["r1", "r2"] + VRFS = ["default", "default"] + AS_NUM = [100, 100] + + for dut, vrf, as_num in zip(DUT, VRFS, AS_NUM): + temp = {dut: {"bgp": []}} + input_dict_default.update(temp) + + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + addr_type: {"unicast": {"import": {"vrf": "ISR"}}} + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_default) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Verify ECMP/Next-hop/Imported routes Vs Locally originated " + "routes/eBGP routes vs iBGP routes --already covered in almost" + " all tests" + ) + + for addr_type in ADDR_TYPES: + + step("Verify Pre-emption") + + input_routes_r3 = { + "r3": {"static_routes": [{"network": [NETWORK3_3[addr_type]]}]} + } + + intf_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"]["interface"] + intf_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"]["interface"] + + if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP: + nh_r3_r1 = get_frr_ipv6_linklocal(tgen, "r3", intf=intf_r3_r1) + nh_r4_r1 = get_frr_ipv6_linklocal(tgen, "r4", intf=intf_r4_r1) + else: + nh_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"][addr_type].split("/")[ + 0 + ] + nh_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"][addr_type].split("/")[ + 0 + ] + + result = verify_bgp_rib( + tgen, addr_type, "r1", input_routes_r3, next_hop=[nh_r4_r1] + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step("Shutdown interface connected to r1 from r4:") + shutdown_bringup_interface(tgen, "r4", intf_r4_r1, False) + + for addr_type in ADDR_TYPES: + + input_routes_r3 = { + "r3": {"static_routes": [{"network": [NETWORK3_3[addr_type]]}]} + } + + intf_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"]["interface"] + intf_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"]["interface"] + + if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP: + nh_r3_r1 = get_frr_ipv6_linklocal(tgen, "r3", intf=intf_r3_r1) + nh_r4_r1 = get_frr_ipv6_linklocal(tgen, "r4", intf=intf_r4_r1) + else: + nh_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"][addr_type].split("/")[ + 0 + ] + nh_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"][addr_type].split("/")[ + 0 + ] + + step("Verify next-hop is changed") + result = verify_bgp_rib( + tgen, addr_type, "r1", input_routes_r3, next_hop=[nh_r3_r1] + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step("Bringup interface connected to r1 from r4:") + shutdown_bringup_interface(tgen, "r4", intf_r4_r1, True) + + for addr_type in ADDR_TYPES: + + input_routes_r3 = { + "r3": {"static_routes": [{"network": [NETWORK3_3[addr_type]]}]} + } + + intf_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"]["interface"] + intf_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"]["interface"] + + if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP: + nh_r3_r1 = get_frr_ipv6_linklocal(tgen, "r3", intf=intf_r3_r1) + nh_r4_r1 = get_frr_ipv6_linklocal(tgen, "r4", intf=intf_r4_r1) + else: + nh_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"][addr_type].split("/")[ + 0 + ] + nh_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"][addr_type].split("/")[ + 0 + ] + + step("Verify next-hop is not chnaged aftr shutdown:") + result = verify_bgp_rib( + tgen, addr_type, "r1", input_routes_r3, next_hop=[nh_r3_r1] + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step("Active-Standby scenario(as-path prepend and Local pref)") + + for addr_type in ADDR_TYPES: + + step("Create prefix-list") + + input_dict_pf = { + "r1": { + "prefix_lists": { + addr_type: { + "pf_ls_{}".format(addr_type): [ + { + "seqid": 10, + "network": NETWORK3_4[addr_type], + "action": "permit", + } + ] + } + } + } + } + result = create_prefix_lists(tgen, input_dict_pf) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + + step("Create route-map to match prefix-list and set localpref 500") + + input_dict_rm = { + "r1": { + "route_maps": { + "rmap_PATH1_{}".format(addr_type): [ + { + "action": "permit", + "seq_id": 10, + "match": { + addr_type: { + "prefix_lists": "pf_ls_{}".format(addr_type) + } + }, + "set": {"locPrf": 500}, + } + ] + } + } + } + + result = create_route_maps(tgen, input_dict_rm) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Create route-map to match prefix-list and set localpref 600") + + input_dict_rm = { + "r1": { + "route_maps": { + "rmap_PATH2_{}".format(addr_type): [ + { + "action": "permit", + "seq_id": 20, + "match": { + addr_type: { + "prefix_lists": "pf_ls_{}".format(addr_type) + } + }, + "set": {"locPrf": 600}, + } + ] + } + } + } + + result = create_route_maps(tgen, input_dict_rm) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + input_dict_rma = { + "r1": { + "bgp": [ + { + "local_as": "100", + "address_family": { + addr_type: { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r1-link1": { + "route_maps": [ + { + "name": "rmap_PATH1_{}".format( + addr_type + ), + "direction": "in", + } + ] + } + } + }, + "r4": { + "dest_link": { + "r1-link1": { + "route_maps": [ + { + "name": "rmap_PATH2_{}".format( + addr_type + ), + "direction": "in", + } + ] + } + } + }, + } + } + } + }, + } + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_rma) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + dut = "r1" + attribute = "locPrf" + + for addr_type in ADDR_TYPES: + + step("Verify bestpath is installed as per highest localpref") + + input_routes_r3 = { + "r3": { + "static_routes": [ + {"network": [NETWORK3_3[addr_type], NETWORK3_4[addr_type]]} + ] + } + } + + result = verify_best_path_as_per_bgp_attribute( + tgen, addr_type, dut, input_routes_r3, attribute + ) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + + step("Create route-map to match prefix-list and set localpref 700") + + input_dict_rm = { + "r1": { + "route_maps": { + "rmap_PATH1_{}".format(addr_type): [ + { + "action": "permit", + "seq_id": 10, + "match": { + addr_type: { + "prefix_lists": "pf_ls_{}".format(addr_type) + } + }, + "set": {"locPrf": 700}, + } + ] + } + } + } + + result = create_route_maps(tgen, input_dict_rm) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + + step("Verify bestpath is changed as per highest localpref") + + input_routes_r3 = { + "r3": { + "static_routes": [ + {"network": [NETWORK3_3[addr_type], NETWORK3_4[addr_type]]} + ] + } + } + + result = verify_best_path_as_per_bgp_attribute( + tgen, addr_type, dut, input_routes_r3, attribute + ) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + + step("Create route-map to match prefix-list and set as-path prepend") + + input_dict_rm = { + "r1": { + "route_maps": { + "rmap_PATH2_{}".format(addr_type): [ + { + "action": "permit", + "seq_id": 20, + "match": { + addr_type: { + "prefix_lists": "pf_ls_{}".format(addr_type) + } + }, + "set": { + "localpref": 700, + "path": {"as_num": "111", "as_action": "prepend"}, + }, + } + ] + } + } + } + + result = create_route_maps(tgen, input_dict_rm) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + attribute = "path" + + for addr_type in ADDR_TYPES: + + step("Verify bestpath is changed as per shortest as-path") + + input_routes_r3 = { + "r3": { + "static_routes": [ + {"network": [NETWORK3_3[addr_type], NETWORK3_4[addr_type]]} + ] + } + } + + result = verify_best_path_as_per_bgp_attribute( + tgen, addr_type, dut, input_routes_r3, attribute + ) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py b/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py new file mode 100644 index 0000000000..e930b62706 --- /dev/null +++ b/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py @@ -0,0 +1,539 @@ +#!/usr/bin/env python + +# +# Copyright (c) 2021 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, +# Inc. ("NetDEF") in this file. +# +# 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 VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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. +# + +""" +Following tests are covered to test BGP VRF Lite: +1. Verify that locally imported routes are selected as best path over eBGP imported routes + peers. +2. Verify ECMP for imported routes from different VRFs. +""" + +import os +import sys +import time +import pytest +import platform +from time import sleep + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) +sys.path.append(os.path.join(CWD, "../lib/")) + +# Required to instantiate the topology builder class. + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib.topogen import Topogen, get_topogen +from lib.topotest import version_cmp + +from lib.common_config import ( + start_topology, + write_test_header, + check_address_types, + write_test_footer, + reset_config_on_routers, + verify_rib, + step, + create_static_routes, + check_router_status, + apply_raw_config +) + +from lib.topolog import logger +from lib.bgp import ( + verify_bgp_convergence, + create_router_bgp, + verify_bgp_rib, + verify_bgp_bestpath +) +from lib.topojson import build_config_from_json + +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + +# Global variables +NETWORK1_1 = {"ipv4": "11.11.11.1/32", "ipv6": "11:11::1/128"} +NETWORK1_2 = {"ipv4": "11.11.11.11/32", "ipv6": "11:11::11/128"} +NETWORK1_3 = {"ipv4": "10.10.10.1/32", "ipv6": "10:10::1/128"} +NETWORK1_4 = {"ipv4": "10.10.10.100/32", "ipv6": "10:10::100/128"} +NETWORK1_5 = {"ipv4": "110.110.110.1/32", "ipv6": "110:110::1/128"} +NETWORK1_6 = {"ipv4": "110.110.110.100/32", "ipv6": "110:110::100/128"} + +NETWORK2_1 = {"ipv4": "22.22.22.2/32", "ipv6": "22:22::2/128"} +NETWORK2_2 = {"ipv4": "22.22.22.22/32", "ipv6": "22:22::22/128"} +NETWORK2_3 = {"ipv4": "20.20.20.20/32", "ipv6": "20:20::20/128"} +NETWORK2_4 = {"ipv4": "20.20.20.200/32", "ipv6": "20:20::200/128"} +NETWORK2_5 = {"ipv4": "220.220.220.20/32", "ipv6": "220:220::20/128"} +NETWORK2_6 = {"ipv4": "220.220.220.200/32", "ipv6": "220:220::200/128"} + +NETWORK3_1 = {"ipv4": "30.30.30.3/32", "ipv6": "30:30::3/128"} +NETWORK3_2 = {"ipv4": "30.30.30.30/32", "ipv6": "30:30::30/128"} + +PREFIX_LIST = { + "ipv4": ["11.11.11.1", "22.22.22.2", "22.22.22.22"], + "ipv6": ["11:11::1", "22:22::2", "22:22::22"], +} +PREFERRED_NEXT_HOP = "global" +VRF_LIST = ["RED", "BLUE", "GREEN"] +COMM_VAL_1 = "100:100" +COMM_VAL_2 = "500:500" +COMM_VAL_3 = "600:600" +BESTPATH = { + "ipv4": "0.0.0.0", + "ipv6": "::" +} + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + + testsuite_run_time = time.asctime(time.localtime(time.time())) + logger.info("Testsuite start time: {}".format(testsuite_run_time)) + logger.info("=" * 40) + + logger.info("Running setup_module to create topology") + + # This function initiates the topology build with Topogen... + json_file = "{}/bgp_vrf_lite_best_path_topo2.json".format(CWD) + tgen = Topogen(json_file, mod.__name__) + global topo + topo = tgen.json_topo + # ... and here it calls Mininet initialization functions. + + # Starting topology, create tmp files which are loaded to routers + # to start deamons and then start routers + start_topology(tgen) + + # Run these tests for kernel version 4.19 or above + if version_cmp(platform.release(), "4.19") < 0: + error_msg = ( + "BGP vrf dynamic route leak tests will not run " + '(have kernel "{}", but it requires >= 4.19)'.format(platform.release()) + ) + pytest.skip(error_msg) + + # Creating configuration from JSON + build_config_from_json(tgen, topo) + + global BGP_CONVERGENCE + global ADDR_TYPES + ADDR_TYPES = check_address_types() + + BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) + assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error: {}".format( + BGP_CONVERGENCE + ) + + logger.info("Running setup_module() done") + + +def teardown_module(): + """Teardown the pytest environment""" + + logger.info("Running teardown_module to delete topology") + + tgen = get_topogen() + + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + logger.info( + "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) + ) + logger.info("=" * 40) + + +##################################################### +# +# Testcases +# +##################################################### + +def test_dynamic_import_ecmp_imported_routed_diffrent_vrfs_p0(request): + """ + Verify ECMP for imported routes from different VRFs. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + if tgen.routers_have_failure(): + check_router_status(tgen) + reset_config_on_routers(tgen) + + step("Configure same static routes in tenant vrfs RED and GREEN on router " + "R3 and redistribute in respective BGP process") + + for vrf_name in ["RED", "GREEN"]: + for addr_type in ADDR_TYPES: + if vrf_name == "GREEN": + next_hop_vrf = topo["routers"]["r1"]["links"][ + "r3-link3"][addr_type].split("/")[0] + else: + next_hop_vrf = topo["routers"]["r2"]["links"][ + "r3-link1"][addr_type].split("/")[0] + static_routes = { + "r3": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "next_hop": next_hop_vrf, + "vrf": vrf_name + } + ] + } + } + + result = create_static_routes(tgen, static_routes) + assert result is True, "Testcase {} :Failed \n Error: {}". \ + format(tc_name, result) + + step("Redistribute static route on BGP VRF : {}".format(vrf_name)) + temp = {} + for addr_type in ADDR_TYPES: + temp.update({ + addr_type: { + "unicast": { + "redistribute": [{ + "redist_type": "static" + }] + } + } + }) + + redist_dict = {"r3": {"bgp": [{ + "vrf": vrf_name, "local_as": 3, "address_family": temp + }]}} + + result = create_router_bgp(tgen, topo, redist_dict) + assert result is True, "Testcase {} :Failed \n Error: {}". \ + format(tc_name, result) + + step("Verify that configured static routes are installed in respective " + "BGP table for vrf RED & GREEN") + for vrf_name in ["RED", "GREEN"]: + for addr_type in ADDR_TYPES: + if vrf_name == "GREEN": + next_hop_vrf = topo["routers"]["r1"]["links"][ + "r3-link3"][addr_type].split("/")[0] + else: + next_hop_vrf = topo["routers"]["r2"]["links"][ + "r3-link1"][addr_type].split("/")[0] + static_routes = { + "r3": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "vrf": vrf_name + } + ] + } + } + + result = verify_bgp_rib(tgen, addr_type, "r3", static_routes, + next_hop=next_hop_vrf) + assert result is True, "Testcase {} : Failed \n Error {}". \ + format(tc_name, result) + + result = verify_rib(tgen, addr_type, "r3", static_routes, + next_hop=next_hop_vrf) + assert result is True, "Testcase {} : Failed \n Error {}". \ + format(tc_name, result) + + step("Import vrf RED and GREEN into default vrf and Configure ECMP") + bgp_val = [] + for vrf_name in ["RED", "GREEN"]: + temp = {} + for addr_type in ADDR_TYPES: + temp.update({ + addr_type: { + "unicast": { + "import": { + "vrf": vrf_name + }, + "maximum_paths": { + "ebgp": 2 + } + } + } + }) + + bgp_val.append({ + "local_as": 3, "address_family": temp + }) + + import_dict = {"r3": {"bgp": bgp_val}} + + result = create_router_bgp(tgen, topo, import_dict) + assert result is True, "Testcase {} :Failed \n Error: {}". \ + format(tc_name, result) + + step("Configure bgp bestpath on router r3") + r3_raw_config = { + "r3": { + "raw_config": [ + "router bgp 3", + "bgp bestpath as-path multipath-relax" + ] + } + } + result = apply_raw_config(tgen, r3_raw_config) + assert result is True, "Testcase {} :Failed \n Error: {}". \ + format(tc_name, result) + + step("Verify that routes are imported with two different next-hop vrfs " + "and IPs. Additionally R3 must do ECMP for both the routes.") + + for addr_type in ADDR_TYPES: + next_hop_vrf = [ + topo["routers"]["r2"]["links"]["r3-link1"][addr_type]. \ + split("/")[0], + topo["routers"]["r1"]["links"]["r3-link3"][addr_type]. \ + split("/")[0] + ] + static_routes = { + "r3": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + } + ] + } + } + + result = verify_bgp_rib(tgen, addr_type, "r3", static_routes, + next_hop=next_hop_vrf) + assert result is True, "Testcase {} : Failed \n Error {}". \ + format(tc_name, result) + + result = verify_rib(tgen, addr_type, "r3", static_routes, + next_hop=next_hop_vrf) + assert result is True, "Testcase {} : Failed \n Error {}". \ + format(tc_name, result) + + step("Now change the next-hop of static routes in vrf RED and GREEN to " + "same IP address") + for addr_type in ADDR_TYPES: + next_hop_vrf = topo["routers"]["r1"]["links"][ + "r3-link3"][addr_type].split("/")[0] + static_routes = { + "r3": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "next_hop": next_hop_vrf, + "vrf": "RED" + }, + { + "network": [NETWORK1_1[addr_type]], + "next_hop": topo["routers"]["r2"]["links"][ + "r3-link1"][addr_type].split("/")[0], + "vrf": "RED", + "delete": True + } + ] + } + } + + result = create_static_routes(tgen, static_routes) + assert result is True, "Testcase {} :Failed \n Error: {}". \ + format(tc_name, result) + + step("Verify that now routes are imported with two different next-hop " + "vrfs but same IPs. Additionally R3 must do ECMP for both the routes") + + for addr_type in ADDR_TYPES: + next_hop_vrf = [ + topo["routers"]["r1"]["links"]["r3-link3"][addr_type].\ + split("/")[0], + topo["routers"]["r1"]["links"]["r3-link3"][addr_type]. \ + split("/")[0] + ] + static_routes = { + "r3": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + } + ] + } + } + + result = verify_bgp_rib(tgen, addr_type, "r3", static_routes, + next_hop=next_hop_vrf) + assert result is True, "Testcase {} : Failed \n Error {}". \ + format(tc_name, result) + + result = verify_rib(tgen, addr_type, "r3", static_routes, + next_hop=next_hop_vrf) + assert result is True, "Testcase {} : Failed \n Error {}". \ + format(tc_name, result) + + write_test_footer(tc_name) + + +def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_p0(request): + """ + Verify ECMP for imported routes from different VRFs. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + if tgen.routers_have_failure(): + check_router_status(tgen) + reset_config_on_routers(tgen) + + step("Configure same static routes on R2 and R3 vrfs and redistribute in BGP " + "for GREEN and RED vrf instances") + for dut, network in zip(["r2", "r3"], [ + [NETWORK1_1, NETWORK1_2], [NETWORK1_1, NETWORK1_2]]): + for vrf_name, network_vrf in zip(["RED", "GREEN"], network): + step("Configure static route for VRF : {} on {}".format(vrf_name, + dut)) + for addr_type in ADDR_TYPES: + static_routes = { + dut: { + "static_routes": [ + { + "network": [network_vrf[addr_type]], + "next_hop": "blackhole", + "vrf": vrf_name + } + ] + } + } + + result = create_static_routes(tgen, static_routes) + assert result is True, "Testcase {} :Failed \n Error: {}". \ + format(tc_name, result) + + for dut, as_num in zip(["r2", "r3"], ["2", "3"]): + for vrf_name in ["RED", "GREEN"]: + step("Redistribute static route on BGP VRF : {}".format(vrf_name)) + temp = {} + for addr_type in ADDR_TYPES: + temp.update({ + addr_type: { + "unicast": { + "redistribute": [{ + "redist_type": "static" + }] + } + } + }) + + redist_dict = {dut: {"bgp": [{ + "vrf": vrf_name, "local_as": as_num, "address_family": temp + }]}} + + result = create_router_bgp(tgen, topo, redist_dict) + assert result is True, "Testcase {} :Failed \n Error: {}". \ + format(tc_name, result) + + step("Verify that R2 and R3 has installed redistributed routes in default " + "and RED vrfs and GREEN respectively:") + for dut, network in zip(["r2", "r3"], + [[NETWORK1_1, NETWORK1_2], + [NETWORK1_1, NETWORK1_2]]): + for vrf_name, network_vrf in zip(["RED", "GREEN"], network): + for addr_type in ADDR_TYPES: + static_routes = { + dut: { + "static_routes": [ + { + "network": [network_vrf[addr_type]], + "next_hop": "blackhole", + "vrf": vrf_name + } + ] + } + } + result = verify_bgp_rib(tgen, addr_type, dut, static_routes) + assert result is True, "Testcase {} : Failed \n Error {}". \ + format(tc_name, result) + + step("Import vrf RED's route in vrf GREEN on R3") + temp = {} + for addr_type in ADDR_TYPES: + temp.update({ + addr_type: { + "unicast": { + "import": { + "vrf": "RED" + } + } + } + }) + + import_dict = {"r3": {"bgp": [{ + "vrf": "GREEN", "local_as": 3, "address_family": temp + }]}} + + result = create_router_bgp(tgen, topo, import_dict) + assert result is True, "Testcase {} :Failed \n Error: {}". \ + format(tc_name, result) + + step("Verify that locally imported routes are installed over eBGP imported" + " routes from VRF RED into VRF GREEN") + for addr_type in ADDR_TYPES: + static_routes = { + "r3": { + "static_routes": [ + { + "network": [NETWORK1_2[addr_type]], + "next_hop": "blackhole", + "vrf": "GREEN" + } + ] + } + } + + input_routes = { + "r3": { + addr_type: [ + { + "network": NETWORK1_2[addr_type], + "bestpath": BESTPATH[addr_type], + "vrf": "GREEN" + } + ] + } + } + + result = verify_bgp_bestpath(tgen, addr_type, input_routes) + assert result is True, "Testcase {} : Failed \n Error {}". \ + format(tc_name, result) + + result = verify_rib(tgen, addr_type, "r3", static_routes) + assert result is True, "Testcase {} : Failed \n Error {}". \ + format(tc_name, result) + + write_test_footer(tc_name) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_vrf_netns/peer1/exa-send.py b/tests/topotests/bgp_vrf_netns/peer1/exa-send.py index 9279cc45ff..ab0eb8ce8f 100755 --- a/tests/topotests/bgp_vrf_netns/peer1/exa-send.py +++ b/tests/topotests/bgp_vrf_netns/peer1/exa-send.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ exa-send.py: Send a few testroutes with ExaBGP diff --git a/tests/topotests/conftest.py b/tests/topotests/conftest.py index ce7878c240..3e1e6eb79b 100755 --- a/tests/topotests/conftest.py +++ b/tests/topotests/conftest.py @@ -9,6 +9,7 @@ import re import subprocess import sys import time +import resource import pytest import lib.fixtures @@ -221,6 +222,9 @@ def pytest_configure(config): is_xdist = True is_worker = True + resource.setrlimit( + resource.RLIMIT_CORE, (resource.RLIM_INFINITY, resource.RLIM_INFINITY) + ) # ----------------------------------------------------- # Set some defaults for the pytest.ini [pytest] section # --------------------------------------------------- @@ -505,5 +509,6 @@ def pytest_runtest_makereport(item, call): # # Add common fixtures available to all tests as parameters # + tgen = pytest.fixture(lib.fixtures.tgen) topo = pytest.fixture(lib.fixtures.topo) diff --git a/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py b/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py index a0cae0a40b..ff9ad6150a 100644 --- a/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py +++ b/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py @@ -175,11 +175,19 @@ def test_isis_route_installation(): for rname, router in tgen.routers().items(): filename = "{0}/{1}/{1}_route.json".format(CWD, rname) expected = json.loads(open(filename, "r").read()) - actual = router.vtysh_cmd( - "show ip route vrf {0}-cust1 json".format(rname), isjson=True - ) - assertmsg = "Router '{}' routes mismatch".format(rname) - assert topotest.json_cmp(actual, expected) is None, assertmsg + + def compare_routing_table(router, expected): + "Helper function to ensure zebra rib convergence" + + actual = router.vtysh_cmd( + "show ip route vrf {0}-cust1 json".format(rname), isjson=True + ) + return topotest.json_cmp(actual, expected) + + test_func = functools.partial(compare_routing_table, router, expected) + (result, diff) = topotest.run_and_expect(test_func, None, count=20, wait=1) + assertmsg = "Router '{}' routes mismatch diff: {}".format(rname, diff) + assert result, assertmsg def test_isis_linux_route_installation(): @@ -220,12 +228,18 @@ def test_isis_route6_installation(): for rname, router in tgen.routers().items(): filename = "{0}/{1}/{1}_route6.json".format(CWD, rname) expected = json.loads(open(filename, "r").read()) - actual = router.vtysh_cmd( - "show ipv6 route vrf {}-cust1 json".format(rname), isjson=True - ) - assertmsg = "Router '{}' routes mismatch".format(rname) - assert topotest.json_cmp(actual, expected) is None, assertmsg + def compare_routing_table(router, expected): + "Helper function to ensure zebra rib convergence" + actual = router.vtysh_cmd( + "show ipv6 route vrf {}-cust1 json".format(rname), isjson=True + ) + return topotest.json_cmp(actual, expected) + + test_func = functools.partial(compare_routing_table, router, expected) + (result, diff) = topotest.run_and_expect(test_func, None, count=20, wait=1) + assertmsg = "Router '{}' routes mismatch diff: ".format(rname, diff) + assert result, assertmsg def test_isis_linux_route6_installation(): diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py index 458ae4b054..3253fe6900 100644 --- a/tests/topotests/lib/bgp.py +++ b/tests/topotests/lib/bgp.py @@ -989,6 +989,14 @@ def __create_bgp_unicast_address_family( if "no_allowas_in" in peer: allow_as_in = peer["no_allowas_in"] config_data.append("no {} allowas-in {}".format(neigh_cxt, allow_as_in)) + + if "shutdown" in peer: + shut_val = peer["shutdown"] + if shut_val is True: + config_data.append("{} shutdown".format(neigh_cxt)) + elif shut_val is False: + config_data.append("no {} shutdown".format(neigh_cxt)) + if prefix_lists: for prefix_list in prefix_lists: name = prefix_list.setdefault("name", {}) @@ -2221,6 +2229,7 @@ def verify_bgp_attributes( rmap_name=None, input_dict=None, seq_id=None, + vrf=None, nexthop=None, expected=True, ): @@ -2275,7 +2284,10 @@ def verify_bgp_attributes( logger.info("Verifying BGP set attributes for dut {}:".format(router)) for static_route in static_routes: - cmd = "show bgp {} {} json".format(addr_type, static_route) + if vrf: + cmd = "show bgp vrf {} {} {} json".format(vrf, addr_type, static_route) + else: + cmd = "show bgp {} {} json".format(addr_type, static_route) show_bgp_json = run_frr_cmd(rnode, cmd, isjson=True) dict_to_test = [] @@ -2821,7 +2833,6 @@ def verify_bgp_rib( st_rt, dut, ) - return errormsg else: nh_found = True @@ -4428,6 +4439,83 @@ def verify_evpn_routes( logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) return False + + +@retry(retry_timeout=10) +def verify_bgp_bestpath(tgen, addr_type, input_dict): + """ + Verifies bgp next hop values in best-path output + + * `dut` : device under test + * `addr_type` : Address type ipv4/ipv6 + * `input_dict`: having details like multipath and bestpath + + Usage + ----- + input_dict_1 = { + "r1": { + "ipv4" : { + "bestpath": "50.0.0.1", + "multipath": ["50.0.0.1", "50.0.0.2"], + "network": "100.0.0.0/24" + } + "ipv6" : { + "bestpath": "1000::1", + "multipath": ["1000::1", "1000::2"] + "network": "2000::1/128" + } + } + } + + result = verify_bgp_bestpath(tgen, input_dict) + + """ + + result = False + logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) + for dut in input_dict.keys(): + rnode = tgen.routers()[dut] + + logger.info("[DUT: %s]: Verifying bgp bestpath and multipath " "routes:", dut) + result = False + for network_dict in input_dict[dut][addr_type]: + nw_addr = network_dict.setdefault("network", None) + vrf = network_dict.setdefault("vrf", None) + bestpath = network_dict.setdefault("bestpath", None) + + if vrf: + cmd = "show bgp vrf {} {} {} bestpath json".format( + vrf, addr_type, nw_addr + ) + else: + cmd = "show bgp {} {} bestpath json".format(addr_type, nw_addr) + + data = run_frr_cmd(rnode, cmd, isjson=True) + route = data["paths"][0] + + if "bestpath" in route: + if route["bestpath"]["overall"] is True: + _bestpath = route["nexthops"][0]["ip"] + + if _bestpath != bestpath: + return ( + "DUT:[{}] Bestpath do not match for" + " network: {}, Expected " + " {} as bgp bestpath found {}".format( + dut, nw_addr, bestpath, _bestpath + ) + ) + + logger.info( + "DUT:[{}] Found expected bestpath: " + " {} for network: {}".format(dut, _bestpath, nw_addr) + ) + result = True + + logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) + return result + + def verify_tcp_mss(tgen, dut, neighbour, configured_tcp_mss, vrf=None): """ This api is used to verify the tcp-mss value assigned to a neigbour of DUT diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py index cf8efdea16..c744e5bbbf 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -26,6 +26,7 @@ import socket import subprocess import sys import traceback +import functools from collections import OrderedDict from copy import deepcopy from datetime import datetime, timedelta @@ -2970,24 +2971,34 @@ def addKernelRoute( logger.info("[DUT: {}]: Running command: [{}]".format(router, cmd)) output = rnode.run(cmd) - # Verifying if ip route added to kernal - result = rnode.run(verify_cmd) - logger.debug("{}\n{}".format(verify_cmd, result)) - if "/" in grp_addr: - ip, mask = grp_addr.split("/") - if mask == "32" or mask == "128": - grp_addr = ip - else: - mask = "32" if addr_type == "ipv4" else "128" + def check_in_kernel(rnode, verify_cmd, grp_addr, router): + # Verifying if ip route added to kernal + errormsg = None + result = rnode.run(verify_cmd) + logger.debug("{}\n{}".format(verify_cmd, result)) + if "/" in grp_addr: + ip, mask = grp_addr.split("/") + if mask == "32" or mask == "128": + grp_addr = ip + else: + mask = "32" if addr_type == "ipv4" else "128" - if not re_search(r"{}".format(grp_addr), result) and mask != "0": - errormsg = ( - "[DUT: {}]: Kernal route is not added for group" - " address {} Config output: {}".format(router, grp_addr, output) - ) + if not re_search(r"{}".format(grp_addr), result) and mask != "0": + errormsg = ( + "[DUT: {}]: Kernal route is not added for group" + " address {} Config output: {}".format( + router, grp_addr, output + ) + ) return errormsg + test_func = functools.partial( + check_in_kernel, rnode, verify_cmd, grp_addr, router + ) + (result, out) = topotest.run_and_expect(test_func, None, count=20, wait=1) + assert result, out + logger.debug("Exiting lib API: addKernelRoute()") return True diff --git a/tests/topotests/lib/ospf.py b/tests/topotests/lib/ospf.py index c425e121af..92d29ad1ab 100644 --- a/tests/topotests/lib/ospf.py +++ b/tests/topotests/lib/ospf.py @@ -265,35 +265,6 @@ def __create_ospf_global(tgen, input_dict, router, build, load_config, ospf): cmd = "no {}".format(cmd) config_data.append(cmd) - # area interface information for ospf6d only - if ospf == "ospf6": - area_iface = ospf_data.setdefault("neighbors", {}) - if area_iface: - for neighbor in area_iface: - if "area" in area_iface[neighbor]: - iface = input_dict[router]["links"][neighbor]["interface"] - cmd = "interface {} area {}".format( - iface, area_iface[neighbor]["area"] - ) - if area_iface[neighbor].setdefault("delete", False): - cmd = "no {}".format(cmd) - config_data.append(cmd) - - try: - if "area" in input_dict[router]["links"][neighbor]["ospf6"]: - iface = input_dict[router]["links"][neighbor]["interface"] - cmd = "interface {} area {}".format( - iface, - input_dict[router]["links"][neighbor]["ospf6"]["area"], - ) - if input_dict[router]["links"][neighbor].setdefault( - "delete", False - ): - cmd = "no {}".format(cmd) - config_data.append(cmd) - except KeyError: - pass - # summary information summary_data = ospf_data.setdefault("summary-address", {}) if summary_data: @@ -363,69 +334,6 @@ def __create_ospf_global(tgen, input_dict, router, build, load_config, ospf): return config_data -def create_router_ospf6( - tgen, topo=None, input_dict=None, build=False, load_config=True -): - """ - API to configure ospf on router - - Parameters - ---------- - * `tgen` : Topogen object - * `topo` : json file data - * `input_dict` : Input dict data, required when configuring from testcase - * `build` : Only for initial setup phase this is set as True. - - Usage - ----- - input_dict = { - "r1": { - "ospf6": { - "router_id": "22.22.22.22", - } - } - - Returns - ------- - True or False - """ - logger.debug("Entering lib API: create_router_ospf6()") - result = False - - if topo is None: - topo = tgen.json_topo - - if not input_dict: - input_dict = deepcopy(topo) - else: - topo = topo["routers"] - input_dict = deepcopy(input_dict) - - config_data_dict = {} - - for router in input_dict.keys(): - if "ospf6" not in input_dict[router]: - logger.debug("Router %s: 'ospf6' not present in input_dict", router) - continue - - config_data = __create_ospf_global( - tgen, input_dict, router, build, load_config, "ospf6" - ) - if config_data: - config_data_dict[router] = config_data - - try: - result = create_common_configurations( - tgen, config_data_dict, "ospf6", build, load_config - ) - except InvalidCLIError: - logger.error("create_router_ospf6", exc_info=True) - result = False - - logger.debug("Exiting lib API: create_router_ospf6()") - return result - - def config_ospf_interface( tgen, topo=None, input_dict=None, build=False, load_config=True ): @@ -874,6 +782,16 @@ def verify_ospf6_neighbor(tgen, topo=None, dut=None, input_dict=None, lan=False) } result = verify_ospf6_neighbor(tgen, topo, dut, input_dict, lan=True) + 3. To check there are no neighbors. + input_dict = { + "r0": { + "ospf6": { + "neighbors": [] + } + } + } + result = verify_ospf6_neighbor(tgen, topo, dut, input_dict) + Returns ------- True or False (Error Message) @@ -904,6 +822,19 @@ def verify_ospf6_neighbor(tgen, topo=None, dut=None, input_dict=None, lan=False) ospf_data_list = input_dict[router]["ospf6"] ospf_nbr_list = ospf_data_list["neighbors"] + # Check if looking for no neighbors + if ospf_nbr_list == []: + if show_ospf_json["neighbors"] == []: + logger.info("[DUT: {}] OSPF6 no neighbors found".format(router)) + return True + else: + errormsg = ( + "[DUT: {}] OSPF6 active neighbors found, expected None".format( + router + ) + ) + return errormsg + for ospf_nbr, nbr_data in ospf_nbr_list.items(): try: diff --git a/tests/topotests/lib/pim.py b/tests/topotests/lib/pim.py index 944981add4..dd2f787014 100644 --- a/tests/topotests/lib/pim.py +++ b/tests/topotests/lib/pim.py @@ -21,8 +21,10 @@ import os import re import sys import traceback +import functools from copy import deepcopy from time import sleep +from lib import topotest # Import common_config to use commomnly used APIs @@ -1481,24 +1483,34 @@ def verify_pim_interface_traffic(tgen, input_dict): rnode = tgen.routers()[dut] logger.info("[DUT: %s]: Verifying pim interface traffic", dut) - show_pim_intf_traffic_json = run_frr_cmd( - rnode, "show ip pim interface traffic json", isjson=True - ) - output_dict[dut] = {} - for intf, data in input_dict[dut].items(): - interface_json = show_pim_intf_traffic_json[intf] - for state in data: + def show_pim_intf_traffic(rnode, dut, input_dict, output_dict): + show_pim_intf_traffic_json = run_frr_cmd( + rnode, "show ip pim interface traffic json", isjson=True + ) - # Verify Tx/Rx - if state in interface_json: - output_dict[dut][state] = interface_json[state] - else: - errormsg = ( - "[DUT %s]: %s is not present" - "for interface %s [FAILED]!! " % (dut, state, intf) - ) - return errormsg + output_dict[dut] = {} + for intf, data in input_dict[dut].items(): + interface_json = show_pim_intf_traffic_json[intf] + for state in data: + + # Verify Tx/Rx + if state in interface_json: + output_dict[dut][state] = interface_json[state] + else: + errormsg = ( + "[DUT %s]: %s is not present" + "for interface %s [FAILED]!! " % (dut, state, intf) + ) + return errormsg + return None + + test_func = functools.partial( + show_pim_intf_traffic, rnode, dut, input_dict, output_dict + ) + (result, out) = topotest.run_and_expect(test_func, None, count=20, wait=1) + if not result: + return out logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) return output_dict diff --git a/tests/topotests/lib/topojson.py b/tests/topotests/lib/topojson.py index 4f23e1ace0..3ca3353ed3 100644 --- a/tests/topotests/lib/topojson.py +++ b/tests/topotests/lib/topojson.py @@ -40,7 +40,7 @@ from lib.common_config import ( topo_daemons, number_to_column, ) -from lib.ospf import create_router_ospf, create_router_ospf6 +from lib.ospf import create_router_ospf from lib.pim import create_igmp_config, create_pim_config from lib.topolog import logger @@ -334,7 +334,6 @@ def build_config_from_json(tgen, topo=None, save_bkup=True): ("igmp", create_igmp_config), ("bgp", create_router_bgp), ("ospf", create_router_ospf), - ("ospf6", create_router_ospf6), ] ) @@ -353,6 +352,18 @@ def build_config_from_json(tgen, topo=None, save_bkup=True): logger.info("build_config_from_json: failed to configure topology") pytest.exit(1) + logger.info("Built config now clearing ospf neighbors as that router-id might not be what is used") + for ospf in ["ospf", "ospf6"]: + for router in data: + if ospf not in data[router]: + continue + + r = tgen.gears[router] + if ospf == "ospf": + r.vtysh_cmd("clear ip ospf process") + else: + r.vtysh_cmd("clear ipv6 ospf6 process") + def create_tgen_from_json(testfile, json_file=None): """Create a topogen object given a testfile. diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index 6ee000b0f4..6be644ac00 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -1386,7 +1386,6 @@ class Router(Node): if params.get("routertype") is not None: self.routertype = params.get("routertype") - self.cmd("ulimit -c unlimited") # Set ownership of config files self.cmd("chown {0}:{0}vty /etc/{0}".format(self.routertype)) @@ -1860,7 +1859,7 @@ class Router(Node): self.cmd("kill -9 %s" % daemonpid) if pid_exists(int(daemonpid)): numRunning += 1 - if wait and numRunning > 0: + while wait and numRunning > 0: sleep( 2, "{}: waiting for {} daemon to be stopped".format( @@ -1884,7 +1883,11 @@ class Router(Node): ) ) self.cmd("kill -9 %s" % daemonpid) - self.cmd("rm -- {}".format(d.rstrip())) + if daemonpid.isdigit() and not pid_exists( + int(daemonpid) + ): + numRunning -= 1 + self.cmd("rm -- {}".format(d.rstrip())) if wait: errors = self.checkRouterCores(reportOnce=True) if self.checkRouterVersion("<", minErrorVersion): diff --git a/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py b/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py index a94dcb505a..38560c06e4 100644 --- a/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py +++ b/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py @@ -848,6 +848,10 @@ def test_new_router_fwd_p0(request): assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) do_countdown(5) + step("Verify again if BSR is installed from bsm forwarded by i1") + result = verify_pim_bsr(tgen, topo, "l1", bsr_ip) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + # Verify ip mroute populated again step("Verify mroute again on l1 (lhr)") result = verify_ip_mroutes(tgen, "l1", src_addr, GROUP_ADDRESS, iif, oil) diff --git a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py index 5e29a1f1fd..2a8e29b1d4 100755 --- a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py +++ b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py @@ -954,11 +954,13 @@ def test_PIM_hello_tx_rx_p1(request): tc_name, result ) - step("verify stats not increamented on c1") + step("verify stats incremented on c1") result = verify_state_incremented(c1_state_before, c1_state_after) assert ( - result is not True - ), "Testcase{} : Failed Error: {}" "stats incremented".format(tc_name, result) + result is True + ), "Testcase{} : Failed Error: {}" "stats is not incremented".format( + tc_name, result + ) step("verify before stats on l1") l1_state_dict = { @@ -991,7 +993,7 @@ def test_PIM_hello_tx_rx_p1(request): tc_name, result ) - step("verify stats not increamented on l1") + step("verify stats not incremented on l1") result = verify_state_incremented(l1_state_before, l1_state_after) assert ( result is not True @@ -1041,10 +1043,10 @@ def test_PIM_hello_tx_rx_p1(request): tc_name, result ) - step("verify stats not increamented on c1") + step("verify stats incremented on c1") result = verify_state_incremented(c1_state_before, c1_state_after) assert ( - result is not True + result is True ), "Testcase{} : Failed Error: {}" "stats incremented".format(tc_name, result) write_test_footer(tc_name) diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py index b80da41bec..fd17180051 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py @@ -408,7 +408,7 @@ def test_ospf_lan_tc1_p0(request): topo_modify_change_ip = deepcopy(topo) intf_ip = topo_modify_change_ip["routers"]["r0"]["links"]["s1"]["ipv4"] topo_modify_change_ip["routers"]["r0"]["links"]["s1"]["ipv4"] = str( - IPv4Address(frr_unicode(intf_ip.split("/")[0])) + 3 + IPv4Address(frr_unicode(intf_ip.split("/")[0])) + 4 ) + "/{}".format(intf_ip.split("/")[1]) build_config_from_json(tgen, topo_modify_change_ip, save_bkup=False) diff --git a/tests/topotests/ospf_dual_stack/test_ospf_dual_stack.json b/tests/topotests/ospf_dual_stack/test_ospf_dual_stack.json index c8a3ce783b..cdb8813b3d 100644 --- a/tests/topotests/ospf_dual_stack/test_ospf_dual_stack.json +++ b/tests/topotests/ospf_dual_stack/test_ospf_dual_stack.json @@ -23,7 +23,8 @@ }, "ospf6": { "hello_interval": 1, - "dead_interval": 4 + "dead_interval": 4, + "area": "1.1.1.1" } } }, @@ -36,9 +37,7 @@ "ospf6": { "router_id": "1.1.1.1", "neighbors": { - "r3": { - "area": "1.1.1.1" - } + "r3": {} } } }, @@ -56,7 +55,8 @@ "ospf6": { "hello_interval": 1, "dead_interval": 4, - "network": "point-to-point" + "network": "point-to-point", + "area": "1.1.1.1" } }, "r4": { @@ -71,7 +71,8 @@ "ospf6": { "hello_interval": 1, "dead_interval": 4, - "network": "point-to-point" + "network": "point-to-point", + "area": "0.0.0.0" } } }, @@ -85,8 +86,8 @@ "ospf6": { "router_id": "2.2.2.2", "neighbors": { - "r3": { "area": "1.1.1.1" }, - "r4": { "area": "0.0.0.0" } + "r3": {}, + "r4": {} } } }, @@ -104,7 +105,8 @@ "ospf6": { "hello_interval": 1, "dead_interval": 4, - "network": "point-to-point" + "network": "point-to-point", + "area": "1.1.1.1" } }, "r2": { @@ -119,7 +121,8 @@ "ospf6": { "hello_interval": 1, "dead_interval": 4, - "network": "point-to-point" + "network": "point-to-point", + "area": "1.1.1.1" } }, "r4": { @@ -134,7 +137,8 @@ "ospf6": { "hello_interval": 1, "dead_interval": 4, - "network": "point-to-point" + "network": "point-to-point", + "area": "0.0.0.0" } } }, @@ -149,9 +153,9 @@ "ospf6": { "router_id": "3.3.3.3", "neighbors": { - "r1": { "area": "1.1.1.1" }, - "r2": { "area": "1.1.1.1" }, - "r4": { "area": "0.0.0.0" } + "r1": {}, + "r2": {}, + "r4": {} } } }, @@ -169,7 +173,8 @@ "ospf6": { "hello_interval": 1, "dead_interval": 4, - "network": "point-to-point" + "network": "point-to-point", + "area": "0.0.0.0" } }, "r3": { @@ -184,7 +189,8 @@ "ospf6": { "hello_interval": 1, "dead_interval": 4, - "network": "point-to-point" + "network": "point-to-point", + "area": "0.0.0.0" } }, "r5": { @@ -199,7 +205,8 @@ "ospf6": { "hello_interval": 1, "dead_interval": 4, - "network": "point-to-point" + "network": "point-to-point", + "area": "2.2.2.2" } } }, @@ -214,9 +221,9 @@ "ospf6": { "router_id": "4.4.4.4", "neighbors": { - "r2": { "area": "0.0.0.0" }, - "r3": { "area": "0.0.0.0" }, - "r5": { "area": "2.2.2.2" } + "r2": {}, + "r3": {}, + "r5": {} } } }, @@ -234,7 +241,8 @@ "ospf6": { "hello_interval": 1, "dead_interval": 4, - "network": "point-to-point" + "network": "point-to-point", + "area": "2.2.2.2" } } }, @@ -247,7 +255,7 @@ "ospf6": { "router_id": "5.5.5.5", "neighbors": { - "r4": { "area": "2.2.2.2" } + "r4": {} } } } diff --git a/tests/topotests/ospfv3_basic_functionality/ospfv3_nssa.json b/tests/topotests/ospfv3_basic_functionality/ospfv3_nssa.json new file mode 100644 index 0000000000..2b91abc9e3 --- /dev/null +++ b/tests/topotests/ospfv3_basic_functionality/ospfv3_nssa.json @@ -0,0 +1,86 @@ +{ + "address_types": [ + "ipv6" + ], + "lo_prefix": { + "ipv6": "2001::", + "v6mask": 128 + }, + "routers": { + "r1": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + }, + "r2": { + "ipv6": "12::1/64", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + } + }, + "ospf6": { + "router_id": "1.1.1.1", + "neighbors": { + "r2": {} + } + } + }, + "r2": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + }, + "r1": { + "ipv6": "12::2/64", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3": { + "ipv6": "23::2/64", + "ospf6": { + "area": "1.1.1.1", + "hello_interval": 1, + "dead_interval": 4 + } + } + }, + "ospf6": { + "router_id": "2.2.2.2", + "neighbors": { + "r1": {}, + "r3": {} + } + } + }, + "r3": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + }, + "r2": { + "ipv6": "23::3/64", + "ospf6": { + "area": "1.1.1.1", + "hello_interval": 1, + "dead_interval": 4 + } + } + }, + "ospf6": { + "router_id": "3.3.3.3", + "neighbors": { + "r2": {} + } + } + } + } +} diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa.py new file mode 100644 index 0000000000..64a067cd1a --- /dev/null +++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa.py @@ -0,0 +1,162 @@ +#!/usr/bin/python + +from lib.topogen import Topogen, get_topogen +from lib.common_config import ( + start_topology, + write_test_header, + write_test_footer, + reset_config_on_routers, + step, + topo_daemons, +) +from lib.topolog import logger +from lib.topojson import build_config_from_json +from lib.ospf import create_router_ospf, verify_ospf6_neighbor +import os +import sys +import time +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, "../")) +sys.path.append(os.path.join(CWD, "../lib/")) + +# pylint: disable=C0413 + +pytestmark = [pytest.mark.ospfd] + + +# Global variables +topo = None + +""" +TOPOOLOGY + + +---+ 0.0.0.0 +---+ 1.1.1.1 +---+ + +R1 +------------+R2 |------------+R3 | + +-+-+ +--++ +--++ + +TESTCASES = +1. OSPF Verify E-bit mismatch between R2 and R3 +2. OSPF Verify N-bit mismatch between R2 and R3 +""" + + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + testsuite_run_time = time.asctime(time.localtime(time.time())) + logger.info("Testsuite start time: {}".format(testsuite_run_time)) + logger.info("=" * 40) + + logger.info("Running setup_module to create topology") + + # This function initiates the topology build with Topogen... + json_file = "{}/ospfv3_nssa.json".format(CWD) + tgen = Topogen(json_file, mod.__name__) + global topo + topo = tgen.json_topo + # ... and here it calls Mininet initialization functions. + + # get list of daemons needs to be started for this suite. + daemons = topo_daemons(tgen, topo) + + # Starting topology, create tmp files which are loaded to routers + # to start deamons and then start routers + start_topology(tgen, daemons) + + # Creating configuration from JSON + build_config_from_json(tgen, topo) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + result = verify_ospf6_neighbor(tgen, topo) + assert result is True, "setup_module: Failed \n Error:" " {}".format(result) + + logger.info("Running setup_module() done") + + +def teardown_module(mod): + """ + Teardown the pytest environment. + + * `mod`: module name + """ + + logger.info("Running teardown_module to delete topology") + + tgen = get_topogen() + + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + logger.info( + "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) + ) + logger.info("=" * 40) + + +# ################################## +# Test cases start here. +# ################################## + + +def test_ospfv3_bit_mismatch(request): + """OSPF verify E-bit and N-bit mismatch.""" + + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + global topo + step("Bring up the base config as per the topology") + reset_config_on_routers(tgen) + + input_dict = {"r3": {"ospf6": {"neighbors": []}}} + + step("Configure r3 as stub router") + stub = {"r3": {"ospf6": {"area": [{"id": "1.1.1.1", "type": "stub"}]}}} + result = create_router_ospf(tgen, topo, stub) + assert result is True, "Testcase {}: Failed \n Error: {}".format(tc_name, result) + # Verify r3 lost its adjacency with r2 due to E-bit mismatch + result = verify_ospf6_neighbor(tgen, topo, dut="r3", input_dict=input_dict) + assert result is True, "Testcase {}: Failed \n Error: {}".format(tc_name, result) + + step("Configure r2 as stub router") + stub = {"r2": {"ospf6": {"area": [{"id": "1.1.1.1", "type": "stub"}]}}} + result = create_router_ospf(tgen, topo, stub) + assert result is True, "Testcase {}: Failed \n Error: {}".format(tc_name, result) + # Verify r3 has an adjacency up with r2 again + result = verify_ospf6_neighbor(tgen, topo, dut="r3") + assert result is True, "Testcase {}: Failed \n Error: {}".format(tc_name, result) + + step("Configure r3 as NSSA router") + nssa = {"r3": {"ospf6": {"area": [{"id": "1.1.1.1", "type": "nssa"}]}}} + result = create_router_ospf(tgen, topo, nssa) + # Verify r3 lost its adjacency with r2 due to N-bit mismatch + result = verify_ospf6_neighbor(tgen, topo, dut="r3", input_dict=input_dict) + assert result is True, "Testcase {}: Failed \n Error: {}".format(tc_name, result) + + step("Configure r2 as NSSA router") + nssa = {"r2": {"ospf6": {"area": [{"id": "1.1.1.1", "type": "nssa"}]}}} + result = create_router_ospf(tgen, topo, nssa) + # Verify r3 has an adjacency up with r2 again + result = verify_ospf6_neighbor(tgen, topo, dut="r3") + assert result is True, "Testcase {}: Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/pim_basic/mcast-rx.py b/tests/topotests/pim_basic/mcast-rx.py index 862ad46af4..885337666a 100755 --- a/tests/topotests/pim_basic/mcast-rx.py +++ b/tests/topotests/pim_basic/mcast-rx.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # mcast-rx.py # diff --git a/tests/topotests/pim_basic/mcast-tx.py b/tests/topotests/pim_basic/mcast-tx.py index 87038ad5cf..88c234573f 100755 --- a/tests/topotests/pim_basic/mcast-tx.py +++ b/tests/topotests/pim_basic/mcast-tx.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # mcast-tx.py # |
