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