summaryrefslogtreecommitdiffstats
path: root/tests/topotests/mgmt_startup
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-09 13:16:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-09 13:16:35 +0000
commite2bbf175a2184bd76f6c54ccf8456babeb1a46fc (patch)
treef0b76550d6e6f500ada964a3a4ee933a45e5a6f1 /tests/topotests/mgmt_startup
parentInitial commit. (diff)
downloadfrr-e2bbf175a2184bd76f6c54ccf8456babeb1a46fc.tar.xz
frr-e2bbf175a2184bd76f6c54ccf8456babeb1a46fc.zip
Adding upstream version 9.1.upstream/9.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/topotests/mgmt_startup')
-rw-r--r--tests/topotests/mgmt_startup/r1/mgmtd.conf13
-rw-r--r--tests/topotests/mgmt_startup/r1/zebra.conf7
-rw-r--r--tests/topotests/mgmt_startup/r2/staticd.conf7
-rw-r--r--tests/topotests/mgmt_startup/r2/zebra.conf12
-rw-r--r--tests/topotests/mgmt_startup/r3/zebra.conf18
-rw-r--r--tests/topotests/mgmt_startup/r4/frr.conf21
-rw-r--r--tests/topotests/mgmt_startup/test_bigconf.py80
-rw-r--r--tests/topotests/mgmt_startup/test_cfgfile_var.py109
-rw-r--r--tests/topotests/mgmt_startup/test_late_bigconf.py98
-rw-r--r--tests/topotests/mgmt_startup/test_late_uniconf.py44
-rw-r--r--tests/topotests/mgmt_startup/test_latestart.py45
-rw-r--r--tests/topotests/mgmt_startup/util.py98
12 files changed, 552 insertions, 0 deletions
diff --git a/tests/topotests/mgmt_startup/r1/mgmtd.conf b/tests/topotests/mgmt_startup/r1/mgmtd.conf
new file mode 100644
index 0000000..ecc829c
--- /dev/null
+++ b/tests/topotests/mgmt_startup/r1/mgmtd.conf
@@ -0,0 +1,13 @@
+debug northbound notifications
+debug northbound libyang
+debug northbound events
+debug northbound callbacks
+debug mgmt backend datastore frontend transaction
+debug mgmt client backend
+debug mgmt client frontend
+
+ip route 12.0.0.0/24 101.0.0.2
+ip route 13.0.0.0/24 101.0.0.3
+
+ipv6 route 2012::/48 2101::2
+ipv6 route 2013::/48 2101::3
diff --git a/tests/topotests/mgmt_startup/r1/zebra.conf b/tests/topotests/mgmt_startup/r1/zebra.conf
new file mode 100644
index 0000000..98cc95b
--- /dev/null
+++ b/tests/topotests/mgmt_startup/r1/zebra.conf
@@ -0,0 +1,7 @@
+log timestamp precision 3
+log file frr2.log
+
+interface r1-eth0
+ ip address 101.0.0.1/24
+ ipv6 address 2101::1/64
+exit \ No newline at end of file
diff --git a/tests/topotests/mgmt_startup/r2/staticd.conf b/tests/topotests/mgmt_startup/r2/staticd.conf
new file mode 100644
index 0000000..b581ed2
--- /dev/null
+++ b/tests/topotests/mgmt_startup/r2/staticd.conf
@@ -0,0 +1,7 @@
+log timestamp precision 3
+
+ip route 11.0.0.0/24 101.0.0.1
+ip route 13.0.0.0/24 101.0.0.3
+
+ipv6 route 2011::/48 2102::1
+ipv6 route 2013::/48 2102::3 \ No newline at end of file
diff --git a/tests/topotests/mgmt_startup/r2/zebra.conf b/tests/topotests/mgmt_startup/r2/zebra.conf
new file mode 100644
index 0000000..1d37a65
--- /dev/null
+++ b/tests/topotests/mgmt_startup/r2/zebra.conf
@@ -0,0 +1,12 @@
+log timestamp precision 3
+debug northbound notifications
+debug northbound libyang
+debug northbound events
+debug northbound callbacks
+debug mgmt backend datastore frontend transaction
+debug mgmt client backend
+debug mgmt client frontend
+
+interface r2-eth0
+ ip address 101.0.0.2/24
+ ipv6 address 2101::2/64
diff --git a/tests/topotests/mgmt_startup/r3/zebra.conf b/tests/topotests/mgmt_startup/r3/zebra.conf
new file mode 100644
index 0000000..8419d74
--- /dev/null
+++ b/tests/topotests/mgmt_startup/r3/zebra.conf
@@ -0,0 +1,18 @@
+log timestamp precision 3
+debug northbound notifications
+debug northbound libyang
+debug northbound events
+debug northbound callbacks
+debug mgmt backend datastore frontend transaction
+debug mgmt client backend
+debug mgmt client frontend
+
+interface r3-eth0
+ ip address 101.0.0.3/24
+ ipv6 address 2101::3/64
+
+ip route 11.0.0.0/24 101.0.0.1
+ip route 12.0.0.0/24 101.0.0.2
+
+ipv6 route 2011::/48 2101::1
+ipv6 route 2012::/48 2101::2
diff --git a/tests/topotests/mgmt_startup/r4/frr.conf b/tests/topotests/mgmt_startup/r4/frr.conf
new file mode 100644
index 0000000..5f3b35d
--- /dev/null
+++ b/tests/topotests/mgmt_startup/r4/frr.conf
@@ -0,0 +1,21 @@
+log timestamp precision 6
+log file frr.log
+
+debug northbound notifications
+debug northbound libyang
+debug northbound events
+debug northbound callbacks
+debug mgmt backend datastore frontend transaction
+debug mgmt client backend
+debug mgmt client frontend
+
+interface r4-eth0
+ ip address 101.0.0.4/24
+ ipv6 address 2101::4/64
+exit
+
+ip route 11.0.0.0/24 101.0.0.1
+ip route 12.0.0.0/24 101.0.0.2
+
+ipv6 route 2012::/48 2101::2
+ipv6 route 2013::/48 2101::3
diff --git a/tests/topotests/mgmt_startup/test_bigconf.py b/tests/topotests/mgmt_startup/test_bigconf.py
new file mode 100644
index 0000000..4f46c8f
--- /dev/null
+++ b/tests/topotests/mgmt_startup/test_bigconf.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 eval: (blacken-mode 1) -*-
+# SPDX-License-Identifier: ISC
+#
+# May 2 2023, Christian Hopps <chopps@labn.net>
+#
+# Copyright (c) 2023, LabN Consulting, L.L.C.
+#
+"""
+Test static route startup functionality
+"""
+
+import datetime
+import logging
+import os
+
+import pytest
+from lib.common_config import step
+from lib.topogen import Topogen, TopoRouter
+from munet.base import Timeout
+from util import check_kernel, check_vtysh_up, write_big_route_conf
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+
+# pytestmark = [pytest.mark.staticd, pytest.mark.mgmtd]
+pytestmark = [pytest.mark.staticd]
+
+
+track = Timeout(0)
+ROUTE_COUNT = 2500
+ROUTE_RANGE = [None, None]
+
+
+@pytest.fixture(scope="module")
+def tgen(request):
+ "Setup/Teardown the environment and provide tgen argument to tests"
+
+ global start_time
+ topodef = {
+ "s1": ("r1",),
+ }
+
+ tgen = Topogen(topodef, request.module.__name__)
+ tgen.start_topology()
+
+ prologue = open(f"{CWD}/r1/mgmtd.conf").read()
+
+ confpath = f"{tgen.gears['r1'].gearlogdir}/r1-late-big.conf"
+ start, end = write_big_route_conf("10.0.0.0/8", ROUTE_COUNT, confpath, prologue)
+ ROUTE_RANGE[0] = start
+ ROUTE_RANGE[1] = end
+
+ # configure mgmtd using current mgmtd config file
+ tgen.gears["r1"].load_config(TopoRouter.RD_ZEBRA, "zebra.conf")
+ tgen.gears["r1"].load_config(TopoRouter.RD_MGMTD, confpath)
+
+ track.started_on = datetime.datetime.now()
+
+ tgen.start_router()
+ yield tgen
+ tgen.stop_topology()
+
+
+def test_staticd_latestart(tgen):
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.routers()["r1"]
+
+ step(f"Verifying {ROUTE_COUNT} startup routes are present")
+
+ check_vtysh_up(r1)
+ logging.info("r1: vtysh connected after %ss", track.elapsed())
+
+ result = check_kernel(r1, ROUTE_RANGE[0], retry_timeout=60)
+ assert result is None
+ logging.info("r1: first route installed after %ss", track.elapsed())
+
+ result = check_kernel(r1, ROUTE_RANGE[1], retry_timeout=60)
+ assert result is None
+ logging.info("r1: last route installed after %ss", track.elapsed())
diff --git a/tests/topotests/mgmt_startup/test_cfgfile_var.py b/tests/topotests/mgmt_startup/test_cfgfile_var.py
new file mode 100644
index 0000000..6a54f71
--- /dev/null
+++ b/tests/topotests/mgmt_startup/test_cfgfile_var.py
@@ -0,0 +1,109 @@
+# -*- coding: utf-8 eval: (blacken-mode 1) -*-
+# SPDX-License-Identifier: ISC
+#
+# May 2 2023, Christian Hopps <chopps@labn.net>
+#
+# Copyright (c) 2023, LabN Consulting, L.L.C.
+#
+"""
+Test static route functionality using old or new configuration files.
+
+User compat:
+
+ - mgmtd split config will first look to `/etc/frr/zebra.conf`
+ then `/etc/frr/staticd.conf` and finally `/etc/frr/mgmtd.conf`
+
+ - When new components are converted to mgmtd their split config should be
+ added here too.
+
+Topotest compat:
+
+ - `mgmtd.conf` is copied to `/etc/frr/` for use by mgmtd when implicit load,
+ or explicit load no config specified.
+
+ - `staticd.conf` is copied to `/etc/frr/` for use by mgmtd when staticd
+ is explicit load implict config, and explicit config.
+
+"""
+
+import pytest
+from lib.common_config import step
+from lib.topogen import Topogen, TopoRouter
+from util import check_kernel
+
+# pytestmark = [pytest.mark.staticd, pytest.mark.mgmtd]
+pytestmark = [pytest.mark.staticd]
+
+
+@pytest.fixture(scope="module")
+def tgen(request):
+ "Setup/Teardown the environment and provide tgen argument to tests"
+
+ topodef = {
+ "s1": ("r1", "r2", "r3", "r4"),
+ }
+
+ tgen = Topogen(topodef, request.module.__name__)
+ tgen.start_topology()
+
+ # configure mgmtd using current mgmtd config file
+ tgen.gears["r1"].load_config(TopoRouter.RD_ZEBRA, "zebra.conf")
+ tgen.gears["r1"].load_config(TopoRouter.RD_MGMTD, "mgmtd.conf")
+
+ # user/topotest compat:
+ # configure mgmtd using old staticd config file, with explicity staticd
+ # load.
+ tgen.gears["r2"].load_config(TopoRouter.RD_ZEBRA, "zebra.conf")
+ tgen.gears["r2"].load_config(TopoRouter.RD_STATIC, "staticd.conf")
+
+ # user compat:
+ # configure mgmtd using backup config file `zebra.conf`
+ tgen.gears["r3"].load_config(TopoRouter.RD_ZEBRA, "zebra.conf")
+
+ # configure mgmtd using current mgmtd config file
+ tgen.gears["r4"].load_frr_config("frr.conf")
+
+ tgen.start_router()
+ yield tgen
+ tgen.stop_topology()
+
+
+def test_staticd_routes_present(tgen):
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for x in ["r1", "r2", "r3", "r4"]:
+ tgen.gears[x].net.cmd_nostatus(
+ "vtysh -c 'debug mgmt client frontend' "
+ "-c 'debug mgmt client backend' "
+ "-c 'debug mgmt backend frontend datastore transaction'"
+ )
+
+ r1 = tgen.routers()["r1"]
+ r2 = tgen.routers()["r2"]
+ r3 = tgen.routers()["r3"]
+ r4 = tgen.routers()["r4"]
+
+ step("Verifying routes are present on r1")
+ result = check_kernel(r1, "12.0.0.0/24")
+ assert result is None
+ result = check_kernel(r1, "13.0.0.0/24")
+ assert result is None
+
+ step("Verifying routes are present on r2")
+ result = check_kernel(r2, "11.0.0.0/24")
+ assert result is None
+ result = check_kernel(r2, "13.0.0.0/24")
+ assert result is None
+
+ step("Verifying routes are present on r3")
+ result = check_kernel(r3, "11.0.0.0/24")
+ assert result is None
+ result = check_kernel(r3, "12.0.0.0/24")
+ assert result is None
+
+ step("Verifying routes are present on r4")
+ result = check_kernel(r4, "11.0.0.0/24")
+ assert result is None
+ result = check_kernel(r4, "12.0.0.0/24")
+ assert result is None
diff --git a/tests/topotests/mgmt_startup/test_late_bigconf.py b/tests/topotests/mgmt_startup/test_late_bigconf.py
new file mode 100644
index 0000000..0b5bf38
--- /dev/null
+++ b/tests/topotests/mgmt_startup/test_late_bigconf.py
@@ -0,0 +1,98 @@
+# -*- coding: utf-8 eval: (blacken-mode 1) -*-
+# SPDX-License-Identifier: ISC
+#
+# May 2 2023, Christian Hopps <chopps@labn.net>
+#
+# Copyright (c) 2023, LabN Consulting, L.L.C.
+#
+
+"""
+Verify large set of routes present when staticd (backend client) is started after it's
+startup config is present during launch.
+"""
+
+import logging
+import os
+
+import pytest
+from lib.common_config import step
+from lib.topogen import Topogen, TopoRouter
+from munet.base import Timeout
+from util import check_kernel, check_vtysh_up, write_big_route_conf
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+
+# pytestmark = [pytest.mark.staticd, pytest.mark.mgmtd]
+pytestmark = [pytest.mark.staticd]
+
+track = Timeout(0)
+ROUTE_COUNT = 2500
+ROUTE_RANGE = [None, None]
+
+
+@pytest.fixture(scope="module")
+def tgen(request):
+ "Setup/Teardown the environment and provide tgen argument to tests"
+
+ global start_time
+ topodef = {
+ "s1": ("r1",),
+ }
+
+ tgen = Topogen(topodef, request.module.__name__)
+ tgen.start_topology()
+
+ prologue = open(f"{CWD}/r1/mgmtd.conf").read()
+
+ confpath = f"{tgen.gears['r1'].gearlogdir}/r1-late-big.conf"
+ start, end = write_big_route_conf("10.0.0.0/8", ROUTE_COUNT, confpath, prologue)
+ ROUTE_RANGE[0] = start
+ ROUTE_RANGE[1] = end
+
+ # configure mgmtd using current mgmtd config file
+ tgen.gears["r1"].load_config(TopoRouter.RD_ZEBRA, "zebra.conf")
+ tgen.gears["r1"].load_config(TopoRouter.RD_MGMTD, confpath)
+
+ # Explicit disable staticd now..
+ tgen.gears["r1"].net.daemons["staticd"] = 0
+
+ tgen.start_router()
+ yield tgen
+ tgen.stop_topology()
+
+
+def test_staticd_latestart(tgen):
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.routers()["r1"]
+
+ check_vtysh_up(r1)
+ logging.info("r1: vtysh connected after %ss", track.elapsed())
+
+ result = check_kernel(r1, ROUTE_RANGE[0], retry_timeout=60, expected=False)
+ assert result is not None, "first route present and should not be"
+ result = check_kernel(r1, ROUTE_RANGE[1], retry_timeout=60, expected=False)
+ assert result is not None, "last route present and should not be"
+
+ step("Starting staticd")
+ t2 = Timeout(0)
+ r1.startDaemons(["staticd"])
+
+ result = check_kernel(r1, ROUTE_RANGE[0], retry_timeout=60)
+ assert result is None, "first route not present and should be"
+ logging.info("r1: elapsed time for first route %ss", t2.elapsed())
+
+ count = 0
+ ocount = 0
+ while count < ROUTE_COUNT:
+ rc, o, e = r1.net.cmd_status("ip -o route | wc -l")
+ if not rc:
+ if count > ocount + 100:
+ ocount = count
+ logging.info("r1: elapsed time for %d routes %s", count, t2.elapsed())
+ count = int(o)
+
+ result = check_kernel(r1, ROUTE_RANGE[1], retry_timeout=1200)
+ assert result is None, "last route not present and should be"
+ logging.info("r1: elapsed time for last route %ss", t2.elapsed())
diff --git a/tests/topotests/mgmt_startup/test_late_uniconf.py b/tests/topotests/mgmt_startup/test_late_uniconf.py
new file mode 100644
index 0000000..d4e7e07
--- /dev/null
+++ b/tests/topotests/mgmt_startup/test_late_uniconf.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 eval: (blacken-mode 1) -*-
+# SPDX-License-Identifier: ISC
+#
+# May 2 2023, Christian Hopps <chopps@labn.net>
+#
+# Copyright (c) 2023, LabN Consulting, L.L.C.
+#
+
+"""
+Verify routes present when staticd (backend client) is started after it's startup
+config, contained inside a unified configuration file, is present during launch.
+"""
+import pytest
+from lib.topogen import Topogen
+from util import _test_staticd_late_start
+
+# pytestmark = [pytest.mark.staticd, pytest.mark.mgmtd]
+pytestmark = [pytest.mark.staticd]
+
+
+@pytest.fixture(scope="module")
+def tgen(request):
+ "Setup/Teardown the environment and provide tgen argument to tests"
+
+ topodef = {
+ "s1": ("r4",),
+ }
+
+ tgen = Topogen(topodef, request.module.__name__)
+ tgen.start_topology()
+
+ # configure mgmtd using current mgmtd config file
+ tgen.gears["r4"].load_frr_config("frr.conf")
+
+ # Explicit disable staticd now..
+ tgen.gears["r4"].net.daemons["staticd"] = 0
+
+ tgen.start_router()
+ yield tgen
+ tgen.stop_topology()
+
+
+def test_staticd_late_start(tgen):
+ return _test_staticd_late_start(tgen, tgen.routers()["r4"])
diff --git a/tests/topotests/mgmt_startup/test_latestart.py b/tests/topotests/mgmt_startup/test_latestart.py
new file mode 100644
index 0000000..1c97b9d
--- /dev/null
+++ b/tests/topotests/mgmt_startup/test_latestart.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 eval: (blacken-mode 1) -*-
+# SPDX-License-Identifier: ISC
+#
+# May 2 2023, Christian Hopps <chopps@labn.net>
+#
+# Copyright (c) 2023, LabN Consulting, L.L.C.
+#
+"""
+Verify routes present when staticd (backend client) is started after it's startup config
+is present during launch.
+"""
+
+import pytest
+from lib.topogen import Topogen, TopoRouter
+from util import _test_staticd_late_start
+
+# pytestmark = [pytest.mark.staticd, pytest.mark.mgmtd]
+pytestmark = [pytest.mark.staticd]
+
+
+@pytest.fixture(scope="module")
+def tgen(request):
+ "Setup/Teardown the environment and provide tgen argument to tests"
+
+ topodef = {
+ "s1": ("r1",),
+ }
+
+ tgen = Topogen(topodef, request.module.__name__)
+ tgen.start_topology()
+
+ # configure mgmtd using current mgmtd config file
+ tgen.gears["r1"].load_config(TopoRouter.RD_ZEBRA, "zebra.conf")
+ tgen.gears["r1"].load_config(TopoRouter.RD_MGMTD)
+
+ # Explicit disable staticd now..
+ tgen.gears["r1"].net.daemons["staticd"] = 0
+
+ tgen.start_router()
+ yield tgen
+ tgen.stop_topology()
+
+
+def test_staticd_late_start(tgen):
+ return _test_staticd_late_start(tgen, tgen.routers()["r1"])
diff --git a/tests/topotests/mgmt_startup/util.py b/tests/topotests/mgmt_startup/util.py
new file mode 100644
index 0000000..e366351
--- /dev/null
+++ b/tests/topotests/mgmt_startup/util.py
@@ -0,0 +1,98 @@
+# -*- coding: utf-8 eval: (blacken-mode 1) -*-
+# SPDX-License-Identifier: ISC
+#
+# May 28 2023, Christian Hopps <chopps@labn.net>
+#
+# Copyright (c) 2023, LabN Consulting, L.L.C.
+#
+
+import ipaddress
+import math
+import re
+
+import pytest
+from lib.common_config import retry, step
+from lib.topolog import logger
+from munet.base import proc_error
+
+
+@retry(retry_timeout=30)
+def check_vtysh_up(router):
+ rc, o, e = router.net.cmd_status("vtysh -c 'show version'")
+ return None if not rc else proc_error(rc, o, e)
+
+
+@retry(retry_timeout=3, initial_wait=0.1)
+def check_kernel(r1, prefix, expected=True):
+ net = ipaddress.ip_network(prefix)
+ if net.version == 6:
+ kernel = r1.net.cmd_nostatus("ip -6 route show", warn=not expected)
+ else:
+ kernel = r1.net.cmd_nostatus("ip -4 route show", warn=not expected)
+
+ logger.debug("checking kernel routing table:\n%0.1920s", kernel)
+ route = f"{str(net)}(?: nhid [0-9]+)?.*proto (static|196)"
+ m = re.search(route, kernel)
+ if expected and not m:
+ return f"Failed to find \n'{route}'\n in \n'{kernel:.1920}'"
+ elif not expected and m:
+ return f"Failed found \n'{route}'\n in \n'{kernel:.1920}'"
+ return None
+
+
+def get_ip_networks(super_prefix, count):
+ count_log2 = math.log(count, 2)
+ if count_log2 != int(count_log2):
+ count_log2 = int(count_log2) + 1
+ else:
+ count_log2 = int(count_log2)
+ network = ipaddress.ip_network(super_prefix)
+ return tuple(network.subnets(count_log2))[0:count]
+
+
+def write_big_route_conf(super_prefix, count, confpath, prologue=""):
+ start = None
+ end = None
+
+ with open(confpath, "w+", encoding="ascii") as f:
+ if prologue:
+ f.write(prologue + "\n")
+ for net in get_ip_networks(super_prefix, count):
+ end = net
+ if not start:
+ start = net
+ f.write(f"ip route {net} lo\n")
+
+ return start, end
+
+
+def _test_staticd_late_start(tgen, router):
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # for x in ["r1"]:
+ # tgen.gears[x].net.cmd_nostatus(
+ # "vtysh -c 'debug mgmt client frontend' "
+ # "-c 'debug mgmt client backend' "
+ # "-c 'debug mgmt backend frontend datastore transaction'"
+ # )
+
+ step("Verifying startup route is not present w/o staticd running")
+ result = check_kernel(router, "12.0.0.0/24", expected=False)
+ assert result is not None
+
+ step("Configure another static route verify is not present w/o staticd running")
+ router.net.cmd_nostatus("vtysh -c 'config t' -c 'ip route 12.1.0.0/24 101.0.0.2'")
+ result = check_kernel(router, "12.0.0.0/24", expected=False)
+ assert result is not None
+ result = check_kernel(router, "12.1.0.0/24", expected=False)
+ assert result is not None
+
+ step("Starting staticd")
+ router.startDaemons(["staticd"])
+
+ step("Verifying both routes are present")
+ result = check_kernel(router, "12.0.0.0/24")
+ assert result is None
+ result = check_kernel(router, "12.1.0.0/24")
+ assert result is None