]> git.puffer.fish Git - mirror/frr.git/commitdiff
topotests: Add test for bgp update-delay configuration 7031/head
authorDon slice <dslice@nvidia.com>
Fri, 28 Aug 2020 19:53:03 +0000 (15:53 -0400)
committerDon Slice <dslice@nvidia.com>
Tue, 8 Sep 2020 11:27:15 +0000 (04:27 -0700)
Signed-off-by: Don Slice <dslice@nvidia.com>
12 files changed:
tests/topotests/bgp_update_delay/__init__.py [new file with mode: 0644]
tests/topotests/bgp_update_delay/r1/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_update_delay/r1/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_update_delay/r2/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_update_delay/r2/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_update_delay/r3/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_update_delay/r3/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_update_delay/r4/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_update_delay/r4/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_update_delay/r5/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_update_delay/r5/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_update_delay/test_bgp_update_delay.py [new file with mode: 0755]

diff --git a/tests/topotests/bgp_update_delay/__init__.py b/tests/topotests/bgp_update_delay/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/topotests/bgp_update_delay/r1/bgpd.conf b/tests/topotests/bgp_update_delay/r1/bgpd.conf
new file mode 100644 (file)
index 0000000..8ebb509
--- /dev/null
@@ -0,0 +1,10 @@
+! exit1
+router bgp 65001
+  no bgp ebgp-requires-policy
+  neighbor 192.168.255.1 remote-as 65002
+  neighbor 192.168.255.1 timers connect 10
+  address-family ipv4 unicast
+    redistribute connected
+  exit-address-family
+  !
+!
diff --git a/tests/topotests/bgp_update_delay/r1/zebra.conf b/tests/topotests/bgp_update_delay/r1/zebra.conf
new file mode 100644 (file)
index 0000000..9904bb4
--- /dev/null
@@ -0,0 +1,9 @@
+! exit1
+interface lo
+ ip address 172.16.255.254/32
+!
+interface r1-eth0
+ ip address 192.168.255.2/30
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_update_delay/r2/bgpd.conf b/tests/topotests/bgp_update_delay/r2/bgpd.conf
new file mode 100644 (file)
index 0000000..438f995
--- /dev/null
@@ -0,0 +1,18 @@
+! spine
+router bgp 65002
+  no bgp ebgp-requires-policy
+  timers bgp 3 9
+  neighbor 192.168.255.2 remote-as 65001
+  neighbor 192.168.254.2 remote-as 65003
+  neighbor 192.168.253.2 remote-as 65004
+  neighbor 192.168.255.2 timers connect 10
+  neighbor 192.168.254.2 timers connect 10
+  neighbor 192.168.253.2 timers connect 10
+!
+ router bgp 65002 vrf vrf1
+  no bgp ebgp-requires-policy
+  timers bgp 3 9
+  neighbor 192.168.252.2 remote-as 65005
+  neighbor 192.168.252.2 timers connect 10
+  !
+!
diff --git a/tests/topotests/bgp_update_delay/r2/zebra.conf b/tests/topotests/bgp_update_delay/r2/zebra.conf
new file mode 100644 (file)
index 0000000..420f00d
--- /dev/null
@@ -0,0 +1,20 @@
+! spine
+interface r2-eth0
+ ip address 192.168.255.1/30
+!
+interface r2-eth1
+ ip address 192.168.254.1/30
+!
+interface r2-eth2
+ ip address 192.168.253.1/30
+!
+interface r2-eth3
+ ip address 192.168.252.1/30
+ vrf vrf1
+!
+auto vrf1
+iface vrf1
+  vrf-table auto
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_update_delay/r3/bgpd.conf b/tests/topotests/bgp_update_delay/r3/bgpd.conf
new file mode 100644 (file)
index 0000000..53e5178
--- /dev/null
@@ -0,0 +1,10 @@
+! exit2
+router bgp 65003
+  no bgp ebgp-requires-policy
+  timers bgp 3 9
+  neighbor 192.168.254.1 remote-as 65002
+  neighbor 192.168.254.1 timers connect 10
+  address-family ipv4 unicast
+    redistribute connected
+  !
+!
diff --git a/tests/topotests/bgp_update_delay/r3/zebra.conf b/tests/topotests/bgp_update_delay/r3/zebra.conf
new file mode 100644 (file)
index 0000000..f490d97
--- /dev/null
@@ -0,0 +1,9 @@
+! exit2
+interface lo
+ ip address 172.16.254.254/32
+!
+interface r3-eth0
+ ip address 192.168.254.2/30
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_update_delay/r4/bgpd.conf b/tests/topotests/bgp_update_delay/r4/bgpd.conf
new file mode 100644 (file)
index 0000000..34cb429
--- /dev/null
@@ -0,0 +1,11 @@
+! exit2
+router bgp 65004
+  no bgp ebgp-requires-policy
+  timers bgp 3 9
+  neighbor 192.168.253.1 remote-as 65002
+  neighbor 192.168.253.1 timers connect 10
+  address-family ipv4 unicast
+    redistribute connected
+  exit-address-family
+  !
+!
diff --git a/tests/topotests/bgp_update_delay/r4/zebra.conf b/tests/topotests/bgp_update_delay/r4/zebra.conf
new file mode 100644 (file)
index 0000000..baba04c
--- /dev/null
@@ -0,0 +1,9 @@
+! exit2
+interface lo
+ ip address 172.16.253.254/32
+!
+interface r4-eth0
+ ip address 192.168.253.2/30
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_update_delay/r5/bgpd.conf b/tests/topotests/bgp_update_delay/r5/bgpd.conf
new file mode 100644 (file)
index 0000000..66ecc70
--- /dev/null
@@ -0,0 +1,11 @@
+! exit1
+router bgp 65005
+  no bgp ebgp-requires-policy
+  timers bgp 3 9
+  neighbor 192.168.252.1 remote-as 65002
+  neighbor 192.168.252.1 timers connect 10
+  address-family ipv4 unicast
+    redistribute connected
+  exit-address-family
+  !
+!
diff --git a/tests/topotests/bgp_update_delay/r5/zebra.conf b/tests/topotests/bgp_update_delay/r5/zebra.conf
new file mode 100644 (file)
index 0000000..8adf6f8
--- /dev/null
@@ -0,0 +1,9 @@
+! exit1
+interface lo
+ ip address 172.16.252.254/32
+!
+interface r1-eth0
+ ip address 192.168.252.2/30
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_update_delay/test_bgp_update_delay.py b/tests/topotests/bgp_update_delay/test_bgp_update_delay.py
new file mode 100755 (executable)
index 0000000..9d2818b
--- /dev/null
@@ -0,0 +1,295 @@
+#!/usr/bin/env python
+
+#
+# test_bgp_update_delay.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2019 by
+# Don Slice <dslice@nvidia.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 the ability to define update-delay to delay bestpath, rib install
+and advertisement to peers when frr is started, restarted or "clear ip
+bgp *" is performed. Test both the vrf-specific and global configuration
+and operation.
+
+r1
+|
+r2----r3
+| \
+|  \
+r5  r4
+
+
+r2 is UUT and peers with r1, r3, and r4 in default bgp instance.
+r2 peers with r5 in vrf vrf1.
+
+Check r2 initial convergence in default table
+Define update-delay with max-delay in the default bgp instance on r2
+Shutdown peering on r1 toward r2 so that delay timers can be exercised
+Clear bgp neighbors on r2 and then check for the 'in progress' indicator
+Check that r2 only installs route learned from r4 after the max-delay timer expires
+Define update-delay with max-delay and estabish-wait and check json output showing set
+Clear neighbors on r2 and check that r3 installs route from r4 after establish-wait time
+Remove update-delay timer on r2 to verify that it goes back to normal behavior
+Clear neighbors on r2 and check that route install time on r2 does not delay
+Define global bgp update-delay with max-delay and establish-wait on r2
+Check that r2 default instance and vrf1 have the max-delay and establish set
+Clear neighbors on r2 and check route-install time is after the establish-wait timer
+
+Note that the keepalive/hold times were changed to 3/9 and the connect retry timer
+to 10 to improve the odds the convergence timing in this test case is useful in the
+event of packet loss.
+"""
+
+import os
+import sys
+import json
+import time
+import pytest
+import functools
+
+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
+from lib.topolog import logger
+from mininet.topo import Topo
+
+
+class TemplateTopo(Topo):
+    def build(self, *_args, **_opts):
+        tgen = get_topogen(self)
+
+        for routern in range(1, 6):
+            tgen.add_router("r{}".format(routern))
+
+        switch = tgen.add_switch("s1")
+        switch.add_link(tgen.gears["r1"])
+        switch.add_link(tgen.gears["r2"])
+
+        switch = tgen.add_switch("s2")
+        switch.add_link(tgen.gears["r2"])
+        switch.add_link(tgen.gears["r3"])
+
+        switch = tgen.add_switch("s3")
+        switch.add_link(tgen.gears["r2"])
+        switch.add_link(tgen.gears["r4"])
+
+        switch = tgen.add_switch("s4")
+        switch.add_link(tgen.gears["r2"])
+        switch.add_link(tgen.gears["r5"])
+
+
+def setup_module(mod):
+    tgen = Topogen(TemplateTopo, mod.__name__)
+    tgen.start_topology()
+
+    router_list = tgen.routers()
+
+    for i, (rname, router) in enumerate(router_list.iteritems(), 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_update_delay():
+    tgen = get_topogen()
+
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    router1 = tgen.gears["r1"]
+    router2 = tgen.gears["r2"]
+    router3 = tgen.gears["r3"]
+
+    # initial convergence without update-delay defined
+    def _bgp_converge(router):
+        output = json.loads(router.vtysh_cmd("show ip bgp neighbor 192.168.255.2 json"))
+        expected = {
+            "192.168.255.2": {
+                "bgpState": "Established",
+                "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 2}},
+            }
+        }
+        return topotest.json_cmp(output, expected)
+
+    def _bgp_check_update_delay(router):
+        output = json.loads(router.vtysh_cmd("show ip bgp sum json"))
+        expected = {"ipv4Unicast": {"updateDelayLimit": 20}}
+
+        return topotest.json_cmp(output, expected)
+
+    def _bgp_check_update_delay_in_progress(router):
+        output = json.loads(router.vtysh_cmd("show ip bgp sum json"))
+        expected = {"ipv4Unicast": {"updateDelayInProgress":True}}
+
+        return topotest.json_cmp(output, expected)
+
+    def _bgp_check_route_install(router):
+        output = json.loads(router.vtysh_cmd("show ip route 172.16.253.254/32 json"))
+        expected = {"172.16.253.254/32": [ {"protocol": "bgp"}]}
+
+        return topotest.json_cmp(output, expected)
+
+    def _bgp_check_update_delay_and_wait(router):
+        output = json.loads(router.vtysh_cmd("show ip bgp sum json"))
+        expected = {
+                "ipv4Unicast": {
+                    "updateDelayLimit": 20,
+                    "updateDelayEstablishWait": 10}}
+
+        return topotest.json_cmp(output, expected)
+
+    def _bgp_check_update_delay(router):
+        output = json.loads(router.vtysh_cmd("show ip bgp sum json"))
+        expected = {"ipv4Unicast": {"updateDelayLimit": 20}}
+
+        return topotest.json_cmp(output, expected)
+
+    def _bgp_check_vrf_update_delay_and_wait(router):
+        output = json.loads(router.vtysh_cmd("show ip bgp vrf vrf1 sum json"))
+        expected = {
+                "ipv4Unicast": {
+                    "updateDelayLimit": 20,
+                    "updateDelayEstablishWait": 10}}
+
+
+        return topotest.json_cmp(output, expected)
+
+
+    # Check r2 initial convergence in default table
+    test_func = functools.partial(_bgp_converge, router2)
+    success, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+
+    assert result is None, 'Failed bgp convergence in "{}"'.format(router2)
+
+    # Define update-delay with max-delay in the default bgp instance on r2
+    router2.vtysh_cmd(
+        """
+          configure terminal
+            router bgp 65002
+              update-delay 20
+        """
+        )
+
+    # Shutdown peering on r1 toward r2 so that delay timers can be exercised
+    router1.vtysh_cmd(
+        """
+          configure terminal
+            router bgp 65001
+              neighbor 192.168.255.1 shut
+        """
+        )
+
+    # Clear bgp neighbors on r2 and then check for the 'in progress' indicator
+    router2.vtysh_cmd("""clear ip bgp *""")
+
+    test_func = functools.partial(_bgp_check_update_delay_in_progress, router2)
+    success, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+
+    assert result is None, 'Failed to set update-delay max-delay timer "{}"'.format(router2)
+
+    # Check that r2 only installs route learned from r4 after the max-delay timer expires
+    test_func = functools.partial(_bgp_check_route_install, router2)
+    success, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+
+    assert result is None, 'Failed to install route after update-delay "{}"'.format(router2)
+
+    # Define update-delay with max-delay and estabish-wait and check json output showing set
+    router2.vtysh_cmd(
+        """
+          configure terminal
+            router bgp 65002
+              update-delay 20 10
+        """
+        )
+
+    test_func = functools.partial(_bgp_check_update_delay_and_wait, router2)
+    success, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+
+    assert result is None, 'Failed to set max-delay and establish-weight timers in "{}"'.format(router2)
+
+    # Define update-delay with max-delay and estabish-wait and check json output showing set
+    router2.vtysh_cmd("""clear ip bgp *""")
+
+    test_func = functools.partial(_bgp_check_route_install, router3)
+    success, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+
+    assert result is None, 'Failed to installed advertised route after establish-wait timer espired "{}"'.format(router2)
+
+    # Remove update-delay timer on r2 to verify that it goes back to normal behavior
+    router2.vtysh_cmd(
+        """
+          configure terminal
+            router bgp 65002
+              no update-delay
+        """
+        )
+
+    # Clear neighbors on r2 and check that route install time on r2 does not delay
+    router2.vtysh_cmd("""clear ip bgp *""")
+
+    test_func = functools.partial(_bgp_check_route_install, router2)
+    success, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+
+    assert result is None, 'Failed to remove update-delay delay timing "{}"'.format(router2)
+
+    # Define global bgp update-delay with max-delay and establish-wait on r2
+    router2.vtysh_cmd(
+        """
+          configure terminal
+            bgp update-delay 20 10
+        """
+        )
+
+    # Check that r2 default instance and vrf1 have the max-delay and establish set
+    test_func = functools.partial(_bgp_check_update_delay_and_wait, router2)
+    success, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+
+    assert result is None, 'Failed to set update-delay in default instance "{}"'.format(router2)
+
+    test_func = functools.partial(_bgp_check_vrf_update_delay_and_wait, router2)
+    success, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+
+    assert result is None, 'Failed to set update-delay in vrf1 "{}"'.format(router2)
+
+    # Clear neighbors on r2 and check route-install time is after the establish-wait timer
+    router2.vtysh_cmd("""clear ip bgp *""")
+
+    test_func = functools.partial(_bgp_check_route_install, router3)
+    success, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+
+    assert result is None, 'Failed to installed advertised route after establish-wait timer espired "{}"'.format(router2)
+
+
+if __name__ == "__main__":
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))