]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/cspf_topo1/test_cspf_topo1.py
doc: Add `show ipv6 rpf X:X::X:X` command to docs
[mirror_frr.git] / tests / topotests / cspf_topo1 / test_cspf_topo1.py
1 #!/usr/bin/env python
2
3 #
4 # test_cspf_topo1.py
5 # Part of NetDEF Topology Tests
6 #
7 # Copyright (c) 2022 by Orange
8 # Author: Olivier Dugeon <olivier.dugeon@orange.com>
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 """
26 test_cspf_topo1.py: Test the FRR Constraint Shortest Path First algorithm.
27
28 +------------+
29 | |
30 | R1 |
31 | 10.0.225.1 |
32 | |
33 +------------+
34 r1-eth0| |r1-eth1
35 | |
36 10.0.0.0/24| |10.0.1.0/24
37 | |2001:db8:1:/64
38 | |
39 r2-eth0| |r2-eth1
40 +------------+ +------------+
41 | | | |
42 | R2 |r2-eth2 r3-eth0| R3 |
43 | 10.0.255.2 +------------------+ 10.0.255.3 |
44 | | 10.0.3.0/24 | |
45 +------------+ 2001:db8:3:/64 +------+-----+
46 r2-eth3| r3-eth1|
47 | |
48 10.0.4.0/24| |
49 | |
50 | |
51 r4-eth0| 2001:db8:5:/64|
52 +------------+ |
53 | | |
54 | R4 |r4-eth1 |
55 | 10.0.255.4 +-------------------------+
56 | |
57 +------------+
58
59 """
60
61 import os
62 import sys
63 import json
64 from functools import partial
65
66 # Save the Current Working Directory to find configuration files.
67 CWD = os.path.dirname(os.path.realpath(__file__))
68 sys.path.append(os.path.join(CWD, "../"))
69
70 # pylint: disable=C0413
71
72 # Import topogen and topotest helpers
73 from lib import topotest
74 from lib.topogen import Topogen, TopoRouter, get_topogen
75 from lib.topolog import logger
76
77 # and Finally pytest
78 import pytest
79
80 pytestmark = [pytest.mark.isisd]
81
82
83 def build_topo(tgen):
84 "Build function"
85
86 # Create 4 routers
87 for routern in range(1, 5):
88 tgen.add_router("r{}".format(routern))
89
90 # Interconect router 1 and 2 with 2 links
91 switch = tgen.add_switch("s1")
92 switch.add_link(tgen.gears["r1"])
93 switch.add_link(tgen.gears["r2"])
94 switch = tgen.add_switch("s2")
95 switch.add_link(tgen.gears["r1"])
96 switch.add_link(tgen.gears["r2"])
97
98 # Interconect router 3 and 2
99 switch = tgen.add_switch("s3")
100 switch.add_link(tgen.gears["r3"])
101 switch.add_link(tgen.gears["r2"])
102
103 # Interconect router 4 and 2
104 switch = tgen.add_switch("s4")
105 switch.add_link(tgen.gears["r4"])
106 switch.add_link(tgen.gears["r2"])
107
108 # Interconnect router 3 and 4
109 switch = tgen.add_switch("s5")
110 switch.add_link(tgen.gears["r3"])
111 switch.add_link(tgen.gears["r4"])
112
113
114 def setup_module(mod):
115 "Sets up the pytest environment"
116
117 logger.info("\n\n---- Starting CSPF tests ----\n")
118
119 tgen = Topogen(build_topo, mod.__name__)
120 tgen.start_topology()
121
122 router_list = tgen.routers()
123
124 for rname, router in router_list.items():
125 router.load_config(
126 TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
127 )
128 router.load_config(
129 TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
130 )
131 if rname == "r1":
132 router.load_config(
133 TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format("r1"))
134 )
135
136 # Initialize all routers.
137 tgen.start_router()
138
139
140 def teardown_module():
141 "Teardown the pytest environment"
142
143 tgen = get_topogen()
144 tgen.stop_topology()
145
146 logger.info("\n\n---- CSPF tests End ----\n")
147
148
149 def compare_ted_json_output(tgen, rname, fileref):
150 "Compare TED JSON output"
151
152 logger.info('Comparing router "%s" TED output', rname)
153
154 filename = "{}/reference/{}".format(CWD, fileref)
155 expected = json.loads(open(filename).read())
156 command = "show sharp ted json"
157
158 # Run test function until we get an result. Wait at most 60 seconds.
159 test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected)
160 _, diff = topotest.run_and_expect(test_func, None, count=60, wait=2)
161 assertmsg = '"{}" TED JSON output mismatches the expected result'.format(rname)
162 assert diff is None, assertmsg
163
164
165 def compare_cspf_output(tgen, rname, fileref, src, dst, cost, bw=""):
166 "Compare CSPF output"
167
168 logger.info('Comparing router "%s" CSPF output', rname)
169
170 filename = "{}/reference/{}".format(CWD, fileref)
171 expected = open(filename).read()
172 command = "show sharp cspf source {} destination {} {} {}".format(
173 src, dst, cost, bw
174 )
175
176 # Run test function until we get an result. Wait at most 60 seconds.
177 test_func = partial(
178 topotest.router_output_cmp, tgen.gears[rname], command, expected
179 )
180 result, diff = topotest.run_and_expect(test_func, "", count=5, wait=2)
181 assert result, "CSPF output mismatches the expected result on {}:\n{}".format(
182 rname, diff
183 )
184
185
186 def setup_testcase(msg):
187 "Setup test case"
188
189 logger.info(msg)
190 tgen = get_topogen()
191
192 # Skip if previous fatal error condition is raised
193 if tgen.routers_have_failure():
194 pytest.skip(tgen.errors)
195
196 return tgen
197
198
199 # Note that all routers must discover the same Network Topology, so the same TED.
200
201
202 def test_step1():
203 "Step1: Check initial topology"
204
205 tgen = setup_testcase("Step1: test initial IS-IS TE Data Base import")
206 tgen.net["r1"].cmd('vtysh -c "sharp import-te"')
207
208 compare_ted_json_output(tgen, "r1", "sharp-ted.json")
209
210
211 def test_step2():
212 "Step2: Test CSPF from r1 to r4 for IPv4 with various metric"
213
214 tgen = setup_testcase("Step2: CSPF(r1, r4, IPv4)")
215
216 compare_cspf_output(
217 tgen, "r1", "cspf-ipv4-metric.txt", "10.0.0.1", "10.0.255.4", "metric 50"
218 )
219 compare_cspf_output(
220 tgen, "r1", "cspf-ipv4-te-metric.txt", "10.0.255.1", "10.0.4.4", "te-metric 50"
221 )
222 compare_cspf_output(
223 tgen, "r1", "cspf-ipv4-delay.txt", "10.0.255.1", "10.0.255.4", "delay 50000"
224 )
225 compare_cspf_output(
226 tgen,
227 "r1",
228 "cspf-ipv4-delay.txt",
229 "10.0.255.1",
230 "10.0.255.4",
231 "delay 50000",
232 "rsv 7 1000000",
233 )
234
235
236 def test_step3():
237 "Step3: Test CSPF from r1 to r4 for IPv6 with various metric"
238
239 tgen = setup_testcase("Step2: CSPF(r1, r4, IPv6)")
240
241 compare_cspf_output(
242 tgen,
243 "r1",
244 "cspf-ipv6-metric.txt",
245 "2001:db8:1::1:1",
246 "2001:db8::4",
247 "metric 50",
248 )
249 compare_cspf_output(
250 tgen,
251 "r1",
252 "cspf-ipv6-te-metric.txt",
253 "2001:db8::1",
254 "2001:db8:5::3:4",
255 "te-metric 80",
256 )
257 compare_cspf_output(
258 tgen, "r1", "cspf-ipv6-delay.txt", "2001:db8::1", "2001:db8::4", "delay 80000"
259 )
260 compare_cspf_output(
261 tgen,
262 "r1",
263 "cspf-ipv6-delay.txt",
264 "2001:db8::1",
265 "2001:db8::4",
266 "delay 80000",
267 "rsv 7 1000000",
268 )
269
270
271 def test_step4():
272 "Step4: Test CSPF from r1 to r4 with no possible path"
273
274 tgen = setup_testcase("Step2: CSPF(r1, r4, failure)")
275
276 compare_cspf_output(
277 tgen, "r1", "cspf-failed.txt", "10.0.255.1", "10.0.255.4", "metric 10"
278 )
279 compare_cspf_output(
280 tgen, "r1", "cspf-failed.txt", "2001:db8::1", "2001:db8::4", "te-metric 50"
281 )
282 compare_cspf_output(
283 tgen, "r1", "cspf-failed.txt", "10.0.255.1", "10.0.255.4", "delay 5000"
284 )
285 compare_cspf_output(
286 tgen,
287 "r1",
288 "cspf-failed.txt",
289 "2001:db8::1",
290 "2001:db8::4",
291 "delay 80000",
292 "rsv 7 10000000",
293 )
294 compare_cspf_output(
295 tgen, "r1", "cspf-failed-src.txt", "10.0.0.3", "10.0.255.4", "metric 10"
296 )
297 compare_cspf_output(
298 tgen, "r1", "cspf-failed-dst.txt", "10.0.0.1", "10.0.4.40", "metric 10"
299 )
300 compare_cspf_output(
301 tgen, "r1", "cspf-failed-same.txt", "10.0.0.1", "10.0.0.1", "metric 10"
302 )
303
304
305 def test_memory_leak():
306 "Run the memory leak test and report results."
307
308 tgen = get_topogen()
309 if not tgen.is_memleak_enabled():
310 pytest.skip("Memory leak test/report is disabled")
311
312 tgen.report_memory_leaks()
313
314
315 if __name__ == "__main__":
316 args = ["-s"] + sys.argv[1:]
317 sys.exit(pytest.main(args))