Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests: multiple OSPF routers connected to a single switch #14775

Merged
merged 1 commit into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions tests/topotests/ospf_single_switch/r1_frr.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
!
hostname r1
ip forwarding
!
interface r1-eth0
ip address 203.0.113.1/24
ip ospf network point-to-multipoint
ip ospf area 0.0.0.0
!ip ospf prefix-suppression
!
interface r1-eth1
ip address 10.0.1.1/24
ip ospf passive
ip ospf area 0.0.0.0
!
router ospf
ospf router-id 10.0.0.1
!
18 changes: 18 additions & 0 deletions tests/topotests/ospf_single_switch/r2_frr.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
!
hostname r2
ip forwarding
!
interface r2-eth0
ip address 203.0.113.2/24
ip ospf network point-to-multipoint
ip ospf area 0.0.0.0
!ip ospf prefix-suppression
!
interface r2-eth1
ip address 10.0.2.1/24
ip ospf passive
ip ospf area 0.0.0.0
!
router ospf
ospf router-id 10.0.0.2
!
18 changes: 18 additions & 0 deletions tests/topotests/ospf_single_switch/r3_frr.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
!
hostname r3
ip forwarding
!
interface r3-eth0
ip address 203.0.113.3/24
ip ospf network point-to-multipoint
ip ospf area 0.0.0.0
!ip ospf prefix-suppression
!
interface r3-eth1
ip address 10.0.3.1/24
ip ospf passive
ip ospf area 0.0.0.0
!
router ospf
ospf router-id 10.0.0.3
!
18 changes: 18 additions & 0 deletions tests/topotests/ospf_single_switch/r4_frr.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
!
hostname r4
ip forwarding
!
interface r4-eth0
ip address 203.0.113.4/24
ip ospf network point-to-multipoint
ip ospf area 0.0.0.0
!ip ospf prefix-suppression
!
interface r4-eth1
ip address 10.0.4.1/24
ip ospf passive
ip ospf area 0.0.0.0
!
router ospf
ospf router-id 10.0.0.4
!
18 changes: 18 additions & 0 deletions tests/topotests/ospf_single_switch/r5_frr.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
!
hostname r5
ip forwarding
!
interface r5-eth0
ip address 203.0.113.5/24
ip ospf network point-to-multipoint
ip ospf area 0.0.0.0
!ip ospf prefix-suppression
!
interface r5-eth1
ip address 10.0.5.1/24
ip ospf passive
ip ospf area 0.0.0.0
!
router ospf
ospf router-id 10.0.0.5
!
18 changes: 18 additions & 0 deletions tests/topotests/ospf_single_switch/r6_frr.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
!
hostname r6
ip forwarding
!
interface r6-eth0
ip address 203.0.113.6/24
ip ospf network point-to-multipoint
ip ospf area 0.0.0.0
!ip ospf prefix-suppression
!
interface r6-eth1
ip address 10.0.6.1/24
ip ospf passive
ip ospf area 0.0.0.0
!
router ospf
ospf router-id 10.0.0.6
!
18 changes: 18 additions & 0 deletions tests/topotests/ospf_single_switch/r7_frr.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
!
hostname r7
ip forwarding
!
interface r7-eth0
ip address 203.0.113.7/24
ip ospf network point-to-multipoint
ip ospf area 0.0.0.0
!ip ospf prefix-suppression
!
interface r7-eth1
ip address 10.0.7.1/24
ip ospf passive
ip ospf area 0.0.0.0
!
router ospf
ospf router-id 10.0.0.7
!
18 changes: 18 additions & 0 deletions tests/topotests/ospf_single_switch/r8_frr.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
!
hostname r8
ip forwarding
!
interface r8-eth0
ip address 203.0.113.8/24
ip ospf network point-to-multipoint
ip ospf area 0.0.0.0
!ip ospf prefix-suppression
!
interface r8-eth1
ip address 10.0.8.1/24
ip ospf passive
ip ospf area 0.0.0.0
!
router ospf
ospf router-id 10.0.0.8
!
189 changes: 189 additions & 0 deletions tests/topotests/ospf_single_switch/test_ospf_single_switch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
#!/usr/bin/env python
# SPDX-License-Identifier: ISC

#
# Copyright (c) 2023 by
# Adriano Marto Reis <[email protected]>
#

import os
import sys
import json
import subprocess
from functools import partial
import pytest

from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger

from lib.common_config import verify_rib
from lib.ospf import verify_ospf_rib
from _ast import Try

pytestmark = pytest.mark.ospfd

"""
A large set of routers are connected to the same switch. Each router shares a
single network. All shared networks must be reachable from all routers.
"""

TOPOLOGY = """
net1 net2 netN
--- --- ---
| | OSPF-passive |
| | |
+---+---+ +---+---+ +---+---+
| | | | | |
| r1 | | r2 | (...) | rN |
| | | | | |
+---+---+ +---+---+ +---+---+
| | OSPF-active |
| | |
+----------------+--------------------------------+
switch


"""

N_ROUTERS = 8

# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))


def build_topo(tgen):
"Build the topology"

# Create a single switch to connect all the routers
switch = tgen.add_switch("switch")

# Create routers
for router_id in range(1, N_ROUTERS + 1):
router = tgen.add_router(f"r{router_id}")
switch.add_link(router)

# The shared network needs to be connected to something
dummy = tgen.add_switch(f"s{router_id}")
dummy.add_link(router)


def setup_module(mod):
logger.info("OSPF single switch:\n {}".format(TOPOLOGY))

tgen = Topogen(build_topo, mod.__name__)
tgen.start_topology()

# Starting Routers
router_list = tgen.routers()

for rname, router in router_list.items():
logger.info("Loading router %s" % rname)
router.load_frr_config(os.path.join(CWD, "{}_frr.conf".format(rname)))

# Initialize all routers.
tgen.start_router()


def teardown_module(mod):
"Tear-down the test environment"
tgen = get_topogen()
tgen.stop_topology()


def is_iproute2_json_supported():
"""
Checks if the command 'ip -j route' is supported.
"""
try:
output = subprocess.run(['ip', '-j', 'route', 'get', '0.0.0.0'], stdout=subprocess.PIPE).stdout.decode()
json.loads(output)
return True
except json.decoder.JSONDecodeError:
return False


@pytest.mark.skipif(not is_iproute2_json_supported(), reason="'ip -j route' not supported")
def test_all_routes_advertised():
tgen = get_topogen()

if tgen.routers_have_failure():
pytest.skip("Skipped because of router(s) failure")

# networks advertised by each router and the expected next hops
networks = {
"r1": ("10.0.1.0/24", "203.0.113.1"),
"r2": ("10.0.2.0/24", "203.0.113.2"),
"r3": ("10.0.3.0/24", "203.0.113.3"),
"r4": ("10.0.4.0/24", "203.0.113.4"),
"r5": ("10.0.5.0/24", "203.0.113.5"),
"r6": ("10.0.6.0/24", "203.0.113.6"),
"r7": ("10.0.7.0/24", "203.0.113.7"),
"r8": ("10.0.8.0/24", "203.0.113.8"),
}

for router_orig in tgen.routers().keys():
for router_dest, network in networks.items():
if router_orig != router_dest:
input_dict = {
router_orig: {
"static_routes": [
{
"network": network[0],
}
]
}
}
result = verify_ospf_rib(tgen, router_orig, input_dict, next_hop=network[1])
assert result is True, "Error: {}".format(result)
result = verify_rib(tgen, "ipv4", router_orig, input_dict, next_hop=network[1])
assert result is True, "Error: {}".format(result)

check_route(router_orig, network[0], network[1])


def check_route(router_name, network, expected_nexthop):
"""
Checks if the given network is present on the given router and has the
expected next hop.
"""
tgen = get_topogen()
router = tgen.gears[router_name]

expected_response = {
network: [
{
"prefix": network,
"protocol": "ospf",
"nexthops": [
{
"ip": expected_nexthop,
"active": True,
},
],
},
],
}

test_func = partial(
topotest.router_json_cmp,
router,
f"show ip route {network} json",
expected_response,
)
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assert (
result is None
), f"{router_name} (ospfd): no route {network} via {expected_nexthop}"

address = network.split("/")[0]
output = router.cmd(f"ip -j route get {address}")
logger.info(output)
routes = json.loads(output)
assert routes[0]["gateway"] == expected_nexthop, f"{router_name} (kernel): no route {address} via {expected_nexthop}"


if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
Loading