]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/isis_advertise_high_metrics/test_isis_advertise_high_metrics.py
ldpd: changes for code maintainability
[mirror_frr.git] / tests / topotests / isis_advertise_high_metrics / test_isis_advertise_high_metrics.py
1 #!/usr/bin/env python
2
3 #
4 # test_isis_advertise_high_metrics.py
5 # Part of NetDEF Topology Tests
6 #
7 # Copyright (c) 2020 by Volta Networks
8 #
9 # Permission to use, copy, modify, and/or distribute this software
10 # for any purpose with or without fee is hereby granted, provided
11 # that the above copyright notice and this permission notice appear
12 # in all copies.
13 #
14 # THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
15 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
17 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
18 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
20 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21 # OF THIS SOFTWARE.
22 #
23
24 r"""
25 test_isis_advertise_high_metrics.py: Advertise High Metrics FRR ISIS Test
26 """
27
28 import os
29 import re
30 import sys
31 import pytest
32 import json
33 from time import sleep
34 from functools import partial
35
36 # Save the Current Working Directory to find configuration files.
37 CWD = os.path.dirname(os.path.realpath(__file__))
38 sys.path.append(os.path.join(CWD, "../"))
39
40 # pylint: disable=C0413
41 # Import topogen and topotest helpers
42 from lib import topotest
43 from lib.common_config import (
44 retry,
45 stop_router,
46 start_router,
47 )
48 from lib.topogen import Topogen, TopoRouter, get_topogen
49 from lib.topolog import logger
50
51 # Required to instantiate the topology builder class.
52
53 pytestmark = [pytest.mark.isisd]
54
55
56 def build_topo(tgen):
57 "Build function"
58
59 # Add ISIS routers:
60 # r2
61 # / \
62 # r1 r4
63 # \ /
64 # r3
65
66 #
67 # Define FRR Routers
68 #
69 for router in ["r1", "r2", "r3", "r4"]:
70 tgen.add_router(router)
71 #
72 # Define connections
73 #
74 switch = tgen.add_switch("s0")
75 switch.add_link(tgen.gears["r1"], nodeif="eth-r2")
76 switch.add_link(tgen.gears["r2"], nodeif="eth-r1")
77
78 switch = tgen.add_switch("s1")
79 switch.add_link(tgen.gears["r1"], nodeif="eth-r3")
80 switch.add_link(tgen.gears["r3"], nodeif="eth-r1")
81
82 switch = tgen.add_switch("s2")
83 switch.add_link(tgen.gears["r2"], nodeif="eth-r4")
84 switch.add_link(tgen.gears["r4"], nodeif="eth-r2")
85
86 switch = tgen.add_switch("s3")
87 switch.add_link(tgen.gears["r3"], nodeif="eth-r4")
88 switch.add_link(tgen.gears["r4"], nodeif="eth-r3")
89
90
91 def setup_module(mod):
92 "Sets up the pytest environment"
93 tgen = Topogen(build_topo, mod.__name__)
94 tgen.start_topology()
95
96 # For all registered routers, load the zebra configuration file
97 for rname, router in tgen.routers().items():
98 router.load_config(
99 TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
100 )
101 router.load_config(
102 TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
103 )
104
105 # After loading the configurations, this function loads configured daemons.
106 tgen.start_router()
107
108
109 def teardown_module(mod):
110 "Teardown the pytest environment"
111 tgen = get_topogen()
112
113 # This function tears down the whole topology.
114 tgen.stop_topology()
115
116
117 @retry(retry_timeout=60)
118 def _check_interface_metrics(router, expected_metrics):
119 "Verfiy metrics on router's isis interfaces"
120
121 tgen = get_topogen()
122 router = tgen.gears[router]
123 logger.info(f"check_interface_metrics {router}")
124 isis_interface_output = router.vtysh_cmd(
125 "show isis interface detail json"
126 )
127
128 intf_json = json.loads(isis_interface_output)
129 for i in range(len(expected_metrics)):
130 metric = intf_json["areas"][0]["circuits"][i]["interface"]["levels"][0]["metric"]
131 if (metric != expected_metrics[i]):
132 intf_name = intf_json["areas"][0]["circuits"][i]["interface"]["name"]
133 return "{} with expected metric {} on {} got {}".format(
134 router.name, expected_metrics[i], intf_name, metric
135 )
136 return True
137
138
139 def check_interface_metrics(router, expected_metrics):
140 "Verfiy metrics on router's isis interfaces"
141
142 assertmsg = _check_interface_metrics(
143 router, expected_metrics
144 )
145 assert assertmsg is True, assertmsg
146
147
148 @retry(retry_timeout=60)
149 def _check_lsp_metrics(router, lsp, expected_metrics):
150 "Verfiy metrics on router's lsp"
151 tgen = get_topogen()
152 router = tgen.gears[router]
153 logger.info(f"check_lsp_metrics {router}")
154 isis_lsp_output = router.vtysh_cmd(
155 "show isis database detail {}".format(lsp)
156 )
157
158 metrics_list = [int(i) for i in re.findall(r"Metric: (\d+)", isis_lsp_output)]
159 if len(metrics_list) == 0:
160 return False
161 for metric in metrics_list:
162 if metric not in expected_metrics:
163 return "{} with expected metrics {} got {}".format(
164 router.name, expected_metrics, metrics_list
165 )
166
167 return True
168
169
170 def check_lsp_metrics(router, lsp, expected_metrics):
171 "Verfiy metrics on router's lsp"
172
173 assertmsg = _check_lsp_metrics(
174 router, lsp, expected_metrics
175 )
176 assert assertmsg is True, assertmsg
177
178
179 @retry(retry_timeout=60)
180 def _check_ip_route(router, destination, expected_interface):
181 "Verfiy IS-IS route"
182
183 tgen = get_topogen()
184 router = tgen.gears[router]
185 logger.info(f"check_ip_route {router}")
186 route_output = router.vtysh_cmd(
187 "show ip route {} json".format(destination)
188 )
189 route_json = json.loads(route_output)
190
191 interface = route_json[destination][0]["nexthops"][0]["interfaceName"]
192
193 if (interface != expected_interface):
194 return "{} with expected route to {} got {} expected {}".format(
195 router.name, destination, interface, expected_interface
196 )
197
198 return True
199
200
201 def check_ip_route(router, destination, expected_interface):
202 "Verfiy IS-IS route"
203
204 assertmsg = _check_ip_route(
205 router, destination, expected_interface
206 )
207 assert assertmsg is True, assertmsg
208
209
210 def test_isis_daemon_up():
211 "Check isis daemon up before starting test"
212 tgen = get_topogen()
213 # Don't run this test if we have any failure.
214 if tgen.routers_have_failure():
215 pytest.skip(tgen.errors)
216
217 for router in ["r1", "r2", "r3", "r4"]:
218 r = tgen.gears[router]
219 daemons = r.vtysh_cmd(
220 "show daemons"
221 )
222 assert "isisd" in daemons
223
224 # Verify initial metric values.
225 check_lsp_metrics("r1", "r1.00-00", [10, 20])
226 check_lsp_metrics("r2", "r2.00-00", [10, 10])
227 check_lsp_metrics("r3", "r3.00-00", [20, 20])
228 check_lsp_metrics("r4", "r4.00-00", [10, 20])
229
230
231 def test_isis_advertise_high_metrics():
232 "Check that advertise high metrics behaves as expected"
233
234 tgen = get_topogen()
235 net = get_topogen().net
236
237 # Don't run this test if we have any failure.
238 if tgen.routers_have_failure():
239 pytest.skip(tgen.errors)
240
241 logger.info("Testing advertise high metrics basic behavior")
242
243 # Confirm low metrics values on each isis interface on r1
244 r1 = tgen.gears["r1"]
245 check_interface_metrics("r1", [10, 20])
246
247 # Confirm low metrics values within isis database on r1
248 check_lsp_metrics("r1", "r1.00-00", [10, 20])
249
250 # Configure advertise high metrics
251 r1.vtysh_cmd(
252 f"""
253 configure
254 router isis 1
255 advertise-high-metrics
256 """
257 )
258
259 # Confirm high wide metrics values on each isis interface on r1
260 check_interface_metrics("r1", [16777215])
261
262 # Confirm high wide metrics values within isis database on r1
263 check_lsp_metrics("r1", "r1.00-00", [16777215])
264
265 # Remove advertise high metrics
266 r1.vtysh_cmd(
267 f"""
268 configure
269 router isis 1
270 no advertise-high-metrics
271 """
272 )
273
274 # Confirm low metrics values on each isis interface on r1
275 check_interface_metrics("r1", [10, 20])
276
277 # Confirm low metrics values within isis database on r1
278 check_lsp_metrics("r1", "r1.00-00", [10, 20])
279
280
281 def test_isis_advertise_high_metrics_narrow():
282 "Check that advertise high metrics behaves as expected with narrow metrics"
283
284 tgen = get_topogen()
285 net = get_topogen().net
286
287 # Don't run this test if we have any failure.
288 if tgen.routers_have_failure():
289 pytest.skip(tgen.errors)
290
291 logger.info("Testing advertise high metrics with narrow metric style")
292
293 r1 = tgen.gears["r1"]
294
295 # Configure narrow metric-style
296 r1.vtysh_cmd(
297 f"""
298 configure
299 router isis 1
300 metric-style narrow
301 """
302 )
303
304 # Confirm low metrics values on each isis interface on r1
305 check_interface_metrics("r1", [10, 20])
306
307 # Confirm low metrics values within isis database on r1
308 check_lsp_metrics("r1", "r1.00-00", [10, 20])
309
310 # Configure advertise high metrics
311 r1.vtysh_cmd(
312 f"""
313 configure
314 router isis 1
315 advertise-high-metrics
316 """
317 )
318
319 # Confirm high narrow metrics values on each isis interface on r1
320 check_interface_metrics("r1", [63])
321
322 # Confirm high narrow metrics values within isis database on r1
323 check_lsp_metrics("r1", "r1.00-00", [63])
324
325 # Remove advertise high metrics
326 r1.vtysh_cmd(
327 f"""
328 configure
329 router isis 1
330 no advertise-high-metrics
331 """
332 )
333
334 # Confirm low metrics values on each isis interface on r1
335 check_interface_metrics("r1", [10, 20])
336
337 # Confirm low metrics values within isis database on r1
338 check_lsp_metrics("r1", "r1.00-00", [10, 20])
339
340 # Remove narrow metric-style
341 r1.vtysh_cmd(
342 f"""
343 configure
344 router isis 1
345 no metric-style narrow
346 """
347 )
348
349
350 def test_isis_advertise_high_metrics_transition():
351 "Check that advertise high metrics behaves as expected with transition metrics"
352 tgen = get_topogen()
353 net = get_topogen().net
354
355 # Don't run this test if we have any failure.
356 if tgen.routers_have_failure():
357 pytest.skip(tgen.errors)
358
359 logger.info("Testing advertise high metrics with transition metric style")
360
361 r1 = tgen.gears["r1"]
362
363 # Configure transition metric-style
364 r1.vtysh_cmd(
365 f"""
366 configure
367 router isis 1
368 metric-style transition
369 """
370 )
371
372 # Confirm low metrics values on each isis interface on r1
373 check_interface_metrics("r1", [10, 20])
374
375 # Confirm low metrics values within isis database on r1
376 check_lsp_metrics("r1", "r1.00-00", [10, 20])
377
378 # Configure advertise high metrics
379 r1.vtysh_cmd(
380 f"""
381 configure
382 router isis 1
383 advertise-high-metrics
384 """
385 )
386
387 # Confirm high transition metrics values on each isis interface on r1
388 check_interface_metrics("r1", [62])
389
390 # Confirm high transition metrics values within isis database on r1
391 check_lsp_metrics("r1", "r1.00-00", [62])
392
393 # Remove advertise high metrics
394 r1.vtysh_cmd(
395 f"""
396 configure
397 router isis 1
398 no advertise-high-metrics
399 """
400 )
401
402 # Confirm low metrics values on each isis interface on r1
403 check_interface_metrics("r1", [10, 20])
404
405 # Confirm low metrics values within isis database on r1
406 check_lsp_metrics("r1", "r1.00-00", [10, 20])
407
408 # Remove narrow metric-style
409 r1.vtysh_cmd(
410 f"""
411 configure
412 router isis 1
413 no metric-style transition
414 """
415 )
416
417
418 def test_isis_advertise_high_metrics_route():
419 """
420 Topology:
421
422 r2
423 / \
424 r1 r4
425 \ /
426 r3
427
428 Devices are configured with preferred route between r1 and r4:
429 r1 -> r2 -> r4
430 Configure "advertise-high-metrics" on r2 and check that preferred route is:
431 r1 -> r3 -> r4.
432 Shut r3 and check that preferred route is:
433 r1 -> r2 -> r4.
434 """
435 tgen = get_topogen()
436 net = get_topogen().net
437
438 # Don't run this test if we have any failure.
439 if tgen.routers_have_failure():
440 pytest.skip(tgen.errors)
441
442 logger.info("Testing advertise high metrics route behavior")
443
444 r1 = tgen.gears["r1"]
445 r2 = tgen.gears["r2"]
446
447 # Verify the preferred path from r1 to r4 (192.168.1.6) is currently via 192.168.1.1, eth-r2
448 check_ip_route("r1", "192.168.1.6/31", "eth-r2")
449
450 # Configure advertise high metrics on r2
451 r2.vtysh_cmd(
452 f"""
453 configure
454 router isis 1
455 advertise-high-metrics
456 """
457 )
458
459 # Verify the preferred path from r1 to r4 (192.168.1.6) is now via 192.168.1.3, eth-r3
460 check_ip_route("r1", "192.168.1.6/31", "eth-r3")
461
462 # Shutdown r3
463 logger.info("Stop router r3")
464 stop_router(tgen, "r3")
465
466 # Verify the preferred path from r1 to r4 (192.168.1.6) is now via 192.168.1.1, eth-r2
467 check_ip_route("r1", "192.168.1.6/31", "eth-r2")
468
469 # Start r3
470 logger.info("Start router r3")
471 start_router(tgen, "r3")
472
473
474 def test_memory_leak():
475 "Run the memory leak test and report results."
476 tgen = get_topogen()
477 if not tgen.is_memleak_enabled():
478 pytest.skip("Memory leak test/report is disabled")
479
480 tgen.report_memory_leaks()
481
482
483 if __name__ == "__main__":
484 args = ["-s"] + sys.argv[1:]
485 sys.exit(pytest.main(args))