]> git.puffer.fish Git - matthieu/frr.git/commitdiff
tests: add topotest for static routes in VRF
authorIgor Ryzhov <iryzhov@nfware.com>
Fri, 2 Feb 2024 17:37:38 +0000 (19:37 +0200)
committerIgor Ryzhov <iryzhov@nfware.com>
Tue, 6 Feb 2024 12:15:37 +0000 (14:15 +0200)
Test how staticd handles VRF creation/deletion.

Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
tests/topotests/static_vrf/r1/frr.conf [new file with mode: 0644]
tests/topotests/static_vrf/test_static_vrf.py [new file with mode: 0644]

diff --git a/tests/topotests/static_vrf/r1/frr.conf b/tests/topotests/static_vrf/r1/frr.conf
new file mode 100644 (file)
index 0000000..bb373b9
--- /dev/null
@@ -0,0 +1,18 @@
+interface r1-eth0 vrf red
+  ip address 192.0.2.1/23
+exit
+
+interface r1-eth1 vrf blue
+  ip address 192.0.2.129/24
+exit
+
+ip route 198.51.100.1/32 192.0.2.2 nexthop-vrf red
+ip route 198.51.100.1/32 192.0.2.130 nexthop-vrf blue
+ip route 198.51.100.2/32 r1-eth0 nexthop-vrf red
+ip route 198.51.100.2/32 r1-eth1 nexthop-vrf blue
+
+ip route 203.0.113.1/32 192.0.2.130 vrf red nexthop-vrf blue
+ip route 203.0.113.2/32 r1-eth1 vrf red nexthop-vrf blue
+
+ip route 203.0.113.129/32 192.0.2.2 vrf blue nexthop-vrf red
+ip route 203.0.113.130/32 r1-eth0 vrf blue nexthop-vrf red
diff --git a/tests/topotests/static_vrf/test_static_vrf.py b/tests/topotests/static_vrf/test_static_vrf.py
new file mode 100644 (file)
index 0000000..97c0800
--- /dev/null
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 eval: (blacken-mode 1) -*-
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2024 NFWare Inc.
+#
+# noqa: E501
+#
+"""
+Test static route functionality
+"""
+
+import ipaddress
+
+import pytest
+from lib.topogen import Topogen
+from lib.common_config import retry
+
+pytestmark = [pytest.mark.staticd, pytest.mark.mgmtd]
+
+
+@pytest.fixture(scope="module")
+def tgen(request):
+    "Setup/Teardown the environment and provide tgen argument to tests"
+
+    topodef = {"s1": ("r1",), "s2": ("r1",)}
+
+    tgen = Topogen(topodef, request.module.__name__)
+    tgen.start_topology()
+
+    router_list = tgen.routers()
+    for rname, router in router_list.items():
+        # Setup VRF red
+        router.net.add_l3vrf("red", 10)
+        router.net.attach_iface_to_l3vrf(rname + "-eth0", "red")
+        # Setup VRF blue
+        router.net.add_l3vrf("blue", 20)
+        router.net.attach_iface_to_l3vrf(rname + "-eth1", "blue")
+        # Load configuration
+        router.load_frr_config("frr.conf")
+
+    tgen.start_router()
+    yield tgen
+    tgen.stop_topology()
+
+
+@retry(retry_timeout=1, initial_wait=0.1)
+def check_kernel(r1, prefix, nexthops, vrf, expected_p=True, expected_nh=True):
+    vrfstr = f" vrf {vrf}" if vrf else ""
+
+    net = ipaddress.ip_network(prefix)
+    if net.version == 6:
+        kernel = r1.run(f"ip -6 route show{vrfstr} {prefix}")
+    else:
+        kernel = r1.run(f"ip -4 route show{vrfstr} {prefix}")
+
+    if expected_p:
+        assert prefix in kernel, f"Failed to find \n'{prefix}'\n in \n'{kernel:.1920}'"
+    else:
+        assert (
+            prefix not in kernel
+        ), f"Failed found \n'{prefix}'\n in \n'{kernel:.1920}'"
+
+    if not expected_p:
+        return
+
+    for nh in nexthops:
+        if expected_nh:
+            assert f"{nh}" in kernel, f"Failed to find \n'{nh}'\n in \n'{kernel:.1920}'"
+        else:
+            assert (
+                f"{nh}" not in kernel
+            ), f"Failed found \n'{nh}'\n in \n'{kernel:.1920}'"
+
+
+def test_static_vrf(tgen):
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    r1 = tgen.gears["r1"]
+
+    # Check initial configuration
+    check_kernel(r1, "198.51.100.1", ["192.0.2.2", "192.0.2.130"], None)
+    check_kernel(r1, "198.51.100.2", ["r1-eth0", "r1-eth1"], None)
+    check_kernel(r1, "203.0.113.1", ["192.0.2.130"], "red")
+    check_kernel(r1, "203.0.113.2", ["r1-eth1"], "red")
+    check_kernel(r1, "203.0.113.129", ["192.0.2.2"], "blue")
+    check_kernel(r1, "203.0.113.130", ["r1-eth0"], "blue")
+
+    # Delete VRF red
+    r1.net.del_iface("red")
+
+    # Check that "red" nexthops are removed, "blue" nexthops are still there
+    check_kernel(r1, "198.51.100.1", ["192.0.2.2"], None, expected_nh=False)
+    check_kernel(r1, "198.51.100.1", ["192.0.2.130"], None)
+    check_kernel(r1, "198.51.100.2", ["r1-eth0"], None, expected_nh=False)
+    check_kernel(r1, "198.51.100.2", ["r1-eth1"], None)
+    check_kernel(r1, "203.0.113.129", ["192.0.2.2"], "blue", expected_p=False)
+    check_kernel(r1, "203.0.113.130", ["r1-eth0"], "blue", expected_p=False)
+
+    # Delete VRF blue
+    r1.net.del_iface("blue")
+
+    # Check that "blue" nexthops are removed
+    check_kernel(r1, "198.51.100.1", ["192.0.2.130"], None, expected_p=False)
+    check_kernel(r1, "198.51.100.2", ["r1-eth1"], None, expected_p=False)
+
+    # Add VRF red back, attach "eth0" to it
+    r1.net.add_l3vrf("red", 10)
+    r1.net.attach_iface_to_l3vrf("r1-eth0", "red")
+
+    # Check that "red" nexthops are restored
+    check_kernel(r1, "198.51.100.1", ["192.0.2.2"], None)
+    check_kernel(r1, "198.51.100.2", ["r1-eth0"], None)
+
+    # Add VRF blue back, attach "eth1" to it
+    r1.net.add_l3vrf("blue", 20)
+    r1.net.attach_iface_to_l3vrf("r1-eth1", "blue")
+
+    # Check that everything is restored
+    check_kernel(r1, "198.51.100.1", ["192.0.2.2", "192.0.2.130"], None)
+    check_kernel(r1, "198.51.100.2", ["r1-eth0", "r1-eth1"], None)
+    check_kernel(r1, "203.0.113.1", ["192.0.2.130"], "red")
+    check_kernel(r1, "203.0.113.2", ["r1-eth1"], "red")
+    check_kernel(r1, "203.0.113.129", ["192.0.2.2"], "blue")
+    check_kernel(r1, "203.0.113.130", ["r1-eth0"], "blue")