From e2bbf175a2184bd76f6c54ccf8456babeb1a46fc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Tue, 9 Apr 2024 15:16:35 +0200 Subject: Adding upstream version 9.1. Signed-off-by: Daniel Baumann --- tests/topotests/mgmt_startup/r1/mgmtd.conf | 13 +++ tests/topotests/mgmt_startup/r1/zebra.conf | 7 ++ tests/topotests/mgmt_startup/r2/staticd.conf | 7 ++ tests/topotests/mgmt_startup/r2/zebra.conf | 12 +++ tests/topotests/mgmt_startup/r3/zebra.conf | 18 ++++ tests/topotests/mgmt_startup/r4/frr.conf | 21 +++++ tests/topotests/mgmt_startup/test_bigconf.py | 80 ++++++++++++++++ tests/topotests/mgmt_startup/test_cfgfile_var.py | 109 ++++++++++++++++++++++ tests/topotests/mgmt_startup/test_late_bigconf.py | 98 +++++++++++++++++++ tests/topotests/mgmt_startup/test_late_uniconf.py | 44 +++++++++ tests/topotests/mgmt_startup/test_latestart.py | 45 +++++++++ tests/topotests/mgmt_startup/util.py | 98 +++++++++++++++++++ 12 files changed, 552 insertions(+) create mode 100644 tests/topotests/mgmt_startup/r1/mgmtd.conf create mode 100644 tests/topotests/mgmt_startup/r1/zebra.conf create mode 100644 tests/topotests/mgmt_startup/r2/staticd.conf create mode 100644 tests/topotests/mgmt_startup/r2/zebra.conf create mode 100644 tests/topotests/mgmt_startup/r3/zebra.conf create mode 100644 tests/topotests/mgmt_startup/r4/frr.conf create mode 100644 tests/topotests/mgmt_startup/test_bigconf.py create mode 100644 tests/topotests/mgmt_startup/test_cfgfile_var.py create mode 100644 tests/topotests/mgmt_startup/test_late_bigconf.py create mode 100644 tests/topotests/mgmt_startup/test_late_uniconf.py create mode 100644 tests/topotests/mgmt_startup/test_latestart.py create mode 100644 tests/topotests/mgmt_startup/util.py (limited to 'tests/topotests/mgmt_startup') 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 +# +# 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 +# +# 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 +# +# 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 +# +# 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 +# +# 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 +# +# 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 -- cgit v1.2.3