]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / tests / topotests / bfd_ospf_topo1 / test_bfd_ospf_topo1.py
CommitLineData
da78f4fe 1#!/usr/bin/env python
acddc0ed 2# SPDX-License-Identifier: ISC
da78f4fe
G
3
4#
5# test_bfd_ospf_topo1.py
6# Part of NetDEF Topology Tests
7#
8# Copyright (c) 2020 by
9# Network Device Education Foundation, Inc. ("NetDEF")
10#
da78f4fe
G
11
12"""
13test_bfd_ospf_topo1.py:
14
15 +---------+
16 | |
17 eth-rt2 (.1) | RT1 | eth-rt3 (.1)
18 +----------+ 1.1.1.1 +----------+
19 | | | |
20 | +---------+ |
21 | |
22 | 10.0.2.0/24 |
23 | |
24 | eth-rt1 | (.2)
25 | 10.0.1.0/24 +----+----+
26 | | |
27 | | RT3 |
28 | | 3.3.3.3 |
29 | | |
30 (.2) | eth-rt1 +----+----+
31 +----+----+ eth-rt4 | (.1)
32 | | |
33 | RT2 | |
34 | 2.2.2.2 | 10.0.4.0/24 |
35 | | |
36 +----+----+ |
37 (.1) | eth-rt5 eth-rt3 | (.2)
38 | +----+----+
39 | | |
40 | | RT4 |
41 | | 4.4.4.4 |
42 | | |
43 | +----+----+
44 | 10.0.3.0/24 eth-rt5 | (.1)
45 | |
46 | |
47 | 10.0.5.0/24 |
48 | |
49 | +---------+ |
50 | | | |
51 +----------+ RT5 +----------+
52 eth-rt2 (.2) | 5.5.5.5 | eth-rt4 (.2)
53 | |
54 +---------+
55
56"""
57
58import os
59import sys
60import pytest
61import json
da78f4fe 62from time import sleep
da78f4fe
G
63from functools import partial
64
65# Save the Current Working Directory to find configuration files.
66CWD = os.path.dirname(os.path.realpath(__file__))
67sys.path.append(os.path.join(CWD, "../"))
68
69# pylint: disable=C0413
70# Import topogen and topotest helpers
71from lib import topotest
72from lib.topogen import Topogen, TopoRouter, get_topogen
73from lib.topolog import logger
74
3dedee4f 75pytestmark = [pytest.mark.bfdd, pytest.mark.ospfd]
da78f4fe 76
5980ad0a 77
da78f4fe
G
78def setup_module(mod):
79 "Sets up the pytest environment"
8db751b8
CH
80 topodef = {
81 "s1": ("rt1:eth-rt2", "rt2:eth-rt1"),
82 "s2": ("rt1:eth-rt3", "rt3:eth-rt1"),
83 "s3": ("rt2:eth-rt5", "rt5:eth-rt2"),
84 "s4": ("rt3:eth-rt4", "rt4:eth-rt3"),
85 "s5": ("rt4:eth-rt5", "rt5:eth-rt4"),
86 }
87 tgen = Topogen(topodef, mod.__name__)
da78f4fe
G
88 tgen.start_topology()
89
90 router_list = tgen.routers()
91
92 # For all registered routers, load the zebra configuration file
8db751b8 93 for rname, router in router_list.items():
da78f4fe
G
94 router.load_config(
95 TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
96 )
97 router.load_config(
98 TopoRouter.RD_BFD, os.path.join(CWD, "{}/bfdd.conf".format(rname))
99 )
100 router.load_config(
101 TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname))
102 )
103 router.load_config(
104 TopoRouter.RD_OSPF6, os.path.join(CWD, "{}/ospf6d.conf".format(rname))
105 )
106
107 tgen.start_router()
108
109
110def teardown_module(mod):
111 "Teardown the pytest environment"
112 tgen = get_topogen()
113
114 # This function tears down the whole topology.
115 tgen.stop_topology()
116
117
118def print_cmd_result(rname, command):
119 print(get_topogen().gears[rname].vtysh_cmd(command, isjson=False))
120
121
8ff24fd2 122def router_compare_json_output(rname, command, reference, count=40, wait=2):
da78f4fe
G
123 "Compare router JSON output"
124
125 logger.info('Comparing router "%s" "%s" output', rname, command)
126
127 tgen = get_topogen()
128 filename = "{}/{}/{}".format(CWD, rname, reference)
129 expected = json.loads(open(filename).read())
130
8ff24fd2 131 # Run test function until we get an result. Wait at most 80 seconds.
da78f4fe
G
132 test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected)
133 _, diff = topotest.run_and_expect(test_func, None, count=count, wait=wait)
134 assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
135 assert diff is None, assertmsg
136
137
138## TEST STEPS
139
140
141def test_rib_ospf_step1():
142 logger.info("Test (step 1): verify RIB for OSPF")
143 tgen = get_topogen()
144
145 # Skip if previous fatal error condition is raised
146 if tgen.routers_have_failure():
147 pytest.skip(tgen.errors)
148
149 router_compare_json_output(
150 "rt1", "show ip route ospf json", "step1/show_ip_route.ref"
151 )
152 router_compare_json_output(
153 "rt1", "show ipv6 route ospf json", "step1/show_ipv6_route.ref"
154 )
155
156
157def test_bfd_ospf_sessions_step2():
158 logger.info("Test (step 2): verify BFD peers for OSPF")
159 tgen = get_topogen()
160
161 # Skip if previous fatal error condition is raised
162 if tgen.routers_have_failure():
163 pytest.skip(tgen.errors)
164
165 # BFD is just used on three routers
166 for rt in ["rt1", "rt2", "rt3"]:
167 router_compare_json_output(
168 rt, "show bfd peers json", "step2/show_bfd_peers.ref"
169 )
170
171
172def test_bfd_ospf_interface_failure_rt2_step3():
173 logger.info("Test (step 3): Check failover handling with RT2 down")
174 tgen = get_topogen()
175
176 # Skip if previous fatal error condition is raised
177 if tgen.routers_have_failure():
178 pytest.skip(tgen.errors)
179
180 # Let's kill the interface on rt2 and see what happens with the RIB and BFD on rt1
181 tgen.gears["rt2"].link_enable("eth-rt1", enabled=False)
182
183 # By default BFD provides a recovery time of 900ms plus jitter, so let's wait
184 # initial 2 seconds to let the CI not suffer.
7b66f10e 185 topotest.sleep(2, "Wait for BFD down notification")
2d28cbe6 186
da78f4fe 187 router_compare_json_output(
f786c3ee 188 "rt1", "show ip route ospf json", "step3/show_ip_route_rt2_down.ref", 10, 2
da78f4fe
G
189 )
190 router_compare_json_output(
7b66f10e 191 "rt1", "show ipv6 route ospf json", "step3/show_ipv6_route_rt2_down.ref", 10, 2
da78f4fe
G
192 )
193 router_compare_json_output(
7b66f10e 194 "rt1", "show bfd peers json", "step3/show_bfd_peers_rt2_down.ref", 10, 2
da78f4fe
G
195 )
196
197 # Check recovery, this can take some time
198 tgen.gears["rt2"].link_enable("eth-rt1", enabled=True)
199
200 router_compare_json_output(
201 "rt1", "show ip route ospf json", "step3/show_ip_route_healthy.ref"
202 )
203 router_compare_json_output(
204 "rt1", "show ipv6 route ospf json", "step3/show_ipv6_route_healthy.ref"
205 )
206 router_compare_json_output(
207 "rt1", "show bfd peers json", "step3/show_bfd_peers_healthy.ref"
208 )
209
210
211def test_bfd_ospf_interface_failure_rt3_step3():
212 logger.info("Test (step 3): Check failover handling with RT3 down")
213 tgen = get_topogen()
214
215 # Skip if previous fatal error condition is raised
216 if tgen.routers_have_failure():
217 pytest.skip(tgen.errors)
218
219 # Let's kill the interface on rt3 and see what happens with the RIB and BFD on rt1
220 tgen.gears["rt3"].link_enable("eth-rt1", enabled=False)
221
222 # By default BFD provides a recovery time of 900ms plus jitter, so let's wait
223 # initial 2 seconds to let the CI not suffer.
7b66f10e 224 topotest.sleep(2, "Wait for BFD down notification")
da78f4fe 225 router_compare_json_output(
f786c3ee 226 "rt1", "show ip route ospf json", "step3/show_ip_route_rt3_down.ref", 10, 2
da78f4fe
G
227 )
228 router_compare_json_output(
7b66f10e 229 "rt1", "show ipv6 route ospf json", "step3/show_ipv6_route_rt3_down.ref", 10, 2
da78f4fe
G
230 )
231 router_compare_json_output(
7b66f10e 232 "rt1", "show bfd peers json", "step3/show_bfd_peers_rt3_down.ref", 10, 2
da78f4fe
G
233 )
234
235 # Check recovery, this can take some time
236 tgen.gears["rt3"].link_enable("eth-rt1", enabled=True)
237
238 router_compare_json_output(
239 "rt1", "show ip route ospf json", "step3/show_ip_route_healthy.ref"
240 )
241 router_compare_json_output(
242 "rt1", "show ipv6 route ospf json", "step3/show_ipv6_route_healthy.ref"
243 )
244 router_compare_json_output(
245 "rt1", "show bfd peers json", "step3/show_bfd_peers_healthy.ref"
246 )
247
248
249def test_memory_leak():
250 "Run the memory leak test and report results."
251 tgen = get_topogen()
252 if not tgen.is_memleak_enabled():
253 pytest.skip("Memory leak test/report is disabled")
254
255 tgen.report_memory_leaks()
256
257
258if __name__ == "__main__":
259 args = ["-s"] + sys.argv[1:]
260 sys.exit(pytest.main(args))