-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests: add topotest for static routes in VRF
Test how staticd handles VRF creation/deletion. Signed-off-by: Igor Ryzhov <[email protected]>
- Loading branch information
Showing
2 changed files
with
146 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
debug static route | ||
|
||
interface r1-eth0 vrf red | ||
ip address 1.1.1.1/24 | ||
exit | ||
|
||
interface r1-eth1 vrf blue | ||
ip address 2.2.2.1/24 | ||
exit | ||
|
||
ip route 30.30.30.30/32 1.1.1.2 nexthop-vrf red | ||
ip route 30.30.30.30/32 2.2.2.2 nexthop-vrf blue | ||
ip route 31.31.31.31/32 r1-eth0 nexthop-vrf red | ||
ip route 31.31.31.31/32 r1-eth1 nexthop-vrf blue | ||
|
||
ip route 10.10.10.10/32 2.2.2.2 vrf red nexthop-vrf blue | ||
ip route 11.11.11.11/32 r1-eth1 vrf red nexthop-vrf blue | ||
|
||
ip route 20.20.20.20/32 1.1.1.2 vrf blue nexthop-vrf red | ||
ip route 21.21.21.21/32 r1-eth0 vrf blue nexthop-vrf red |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, "30.30.30.30", ["1.1.1.2", "2.2.2.2"], None) | ||
check_kernel(r1, "31.31.31.31", ["r1-eth0", "r1-eth1"], None) | ||
check_kernel(r1, "10.10.10.10", ["2.2.2.2"], "red") | ||
check_kernel(r1, "11.11.11.11", ["r1-eth1"], "red") | ||
check_kernel(r1, "20.20.20.20", ["1.1.1.2"], "blue") | ||
check_kernel(r1, "21.21.21.21", ["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, "30.30.30.30", ["1.1.1.2"], None, expected_nh=False) | ||
check_kernel(r1, "30.30.30.30", ["2.2.2.2"], None) | ||
check_kernel(r1, "31.31.31.31", ["r1-eth0"], None, expected_nh=False) | ||
check_kernel(r1, "31.31.31.31", ["r1-eth1"], None) | ||
check_kernel(r1, "20.20.20.20", ["1.1.1.2"], "blue", expected_p=False) | ||
check_kernel(r1, "21.21.21.21", ["r1-eth0"], "blue", expected_p=False) | ||
|
||
# Delete VRF blue | ||
r1.net.del_iface("blue") | ||
|
||
# Check that "blue" nexthops are removed | ||
check_kernel(r1, "30.30.30.30", ["2.2.2.2"], None, expected_p=False) | ||
check_kernel(r1, "31.31.31.31", ["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, "30.30.30.30", ["1.1.1.2"], None) | ||
check_kernel(r1, "31.31.31.31", ["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, "30.30.30.30", ["1.1.1.2", "2.2.2.2"], None) | ||
check_kernel(r1, "31.31.31.31", ["r1-eth0", "r1-eth1"], None) | ||
check_kernel(r1, "10.10.10.10", ["2.2.2.2"], "red") | ||
check_kernel(r1, "11.11.11.11", ["r1-eth1"], "red") | ||
check_kernel(r1, "20.20.20.20", ["1.1.1.2"], "blue") | ||
check_kernel(r1, "21.21.21.21", ["r1-eth0"], "blue") |