-
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: multiple OSPF routers connected to a single switch
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. Signed-off-by: "Adriano Marto Reis" <[email protected]>
- Loading branch information
1 parent
8e3a96e
commit 3b12cf8
Showing
9 changed files
with
333 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,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 | ||
! |
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,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 | ||
! |
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,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 | ||
! |
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,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 | ||
! |
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,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 | ||
! |
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,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 | ||
! |
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,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 | ||
! |
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,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
189
tests/topotests/ospf_single_switch/test_ospf_single_switch.py
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,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'], stdout=subprocess.PIPE).stdout.decode() | ||
json.loads(output) | ||
return True | ||
except json.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)) |