]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/bgp_features/test_bgp_features.py
Merge pull request #13506 from anlancs/fix/bfdd-vrf-check
[mirror_frr.git] / tests / topotests / bgp_features / test_bgp_features.py
1 #!/usr/bin/env python
2 # SPDX-License-Identifier: ISC
3
4 #
5 # test_bgp_features.py
6 # Part of NetDEF Topology Tests
7 #
8 # Copyright (c) 2020 by
9 # Network Device Education Foundation, Inc. ("NetDEF")
10 #
11
12 """
13 test_bgp_features.py: Test various BGP features.
14 """
15
16 import json
17 import functools
18 import os
19 import sys
20 import pytest
21 import re
22 import time
23
24 # Save the Current Working Directory to find configuration files.
25 CWD = os.path.dirname(os.path.realpath(__file__))
26 sys.path.append(os.path.join(CWD, "../"))
27
28 # pylint: disable=C0413
29 # Import topogen and topotest helpers
30 from lib import topotest
31 from lib.topogen import Topogen, TopoRouter, get_topogen
32 from lib.topolog import logger
33
34 # Required to instantiate the topology builder class.
35
36 pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd]
37
38 #####################################################
39 #
40 # Network Topology Definition
41 #
42 #####################################################
43
44
45 def build_topo(tgen):
46 for rtrNum in range(1, 6):
47 tgen.add_router("r{}".format(rtrNum))
48
49 # create ExaBGP peers
50 for peer_num in range(1, 5):
51 tgen.add_exabgp_peer(
52 "peer{}".format(peer_num),
53 ip="192.168.101.{}".format(peer_num + 2),
54 defaultRoute="via 192.168.101.1",
55 )
56
57 # Setup Switches and connections
58 for swNum in range(1, 11):
59 tgen.add_switch("sw{}".format(swNum))
60
61 # Add connections to stub switches
62 tgen.gears["r1"].add_link(tgen.gears["sw6"])
63 tgen.gears["r2"].add_link(tgen.gears["sw7"])
64 tgen.gears["r3"].add_link(tgen.gears["sw8"])
65 tgen.gears["r4"].add_link(tgen.gears["sw9"])
66 tgen.gears["r5"].add_link(tgen.gears["sw10"])
67
68 # Add connections to R1-R2-R3 core
69 tgen.gears["r1"].add_link(tgen.gears["sw1"])
70 tgen.gears["r1"].add_link(tgen.gears["sw3"])
71 tgen.gears["r2"].add_link(tgen.gears["sw1"])
72 tgen.gears["r2"].add_link(tgen.gears["sw2"])
73 tgen.gears["r3"].add_link(tgen.gears["sw2"])
74 tgen.gears["r3"].add_link(tgen.gears["sw3"])
75
76 # Add connections to external R4/R5 Routers
77 tgen.gears["r1"].add_link(tgen.gears["sw4"])
78 tgen.gears["r4"].add_link(tgen.gears["sw4"])
79 tgen.gears["r2"].add_link(tgen.gears["sw5"])
80 tgen.gears["r5"].add_link(tgen.gears["sw5"])
81
82 # Add ExaBGP peers to sw4
83 tgen.gears["peer1"].add_link(tgen.gears["sw4"])
84 tgen.gears["peer2"].add_link(tgen.gears["sw4"])
85 tgen.gears["peer3"].add_link(tgen.gears["sw4"])
86 tgen.gears["peer4"].add_link(tgen.gears["sw4"])
87
88
89 #####################################################
90 #
91 # Tests starting
92 #
93 #####################################################
94
95
96 def setup_module(module):
97 tgen = Topogen(build_topo, module.__name__)
98 tgen.start_topology()
99
100 # Starting Routers
101 router_list = tgen.routers()
102 for rname, router in router_list.items():
103 router.load_config(
104 TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
105 )
106 if os.path.exists(os.path.join(CWD, "{}/bgpd.conf".format(rname))):
107 logger.info("{} uses BGPd".format(rname))
108 router.load_config(
109 TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
110 )
111 if os.path.exists(os.path.join(CWD, "{}/ospfd.conf".format(rname))):
112 logger.info("{} uses OSPFd".format(rname))
113 router.load_config(
114 TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname))
115 )
116 if os.path.exists(os.path.join(CWD, "{}/ospf6d.conf".format(rname))):
117 logger.info("{} uses OSPF6d".format(rname))
118 router.load_config(
119 TopoRouter.RD_OSPF6, os.path.join(CWD, "{}/ospf6d.conf".format(rname))
120 )
121 router.start()
122
123
124 def teardown_module(module):
125 tgen = get_topogen()
126 tgen.stop_topology()
127
128
129 def test_ospf_convergence():
130 "Test for OSPFv2 topology convergence"
131 tgen = get_topogen()
132
133 # Skip if previous fatal error condition is raised
134 if tgen.routers_have_failure():
135 pytest.skip(tgen.errors)
136
137 # Check Router r1, r2 & r3 OSPF
138 for rtrNum in range(1, 4):
139 logger.info("Checking OSPFv2 convergence on router r{}".format(rtrNum))
140
141 router = tgen.gears["r{}".format(rtrNum)]
142 reffile = os.path.join(CWD, "r{}/ospf_neighbor.json".format(rtrNum))
143 expected = json.loads(open(reffile).read())
144
145 test_func = functools.partial(
146 topotest.router_json_cmp, router, "show ip ospf neighbor json", expected
147 )
148 _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
149 assertmsg = "OSPF router R{} did not converge".format(rtrNum)
150 assert res is None, assertmsg
151
152
153 def test_bgp_convergence():
154 "Test for BGP topology convergence"
155 tgen = get_topogen()
156
157 # Skip if previous fatal error condition is raised
158 if tgen.routers_have_failure():
159 pytest.skip(tgen.errors)
160
161 # Check Router r1 & r2 BGP
162 for rtrNum in [1, 2, 4, 5]:
163 logger.info("Checking BGP IPv4 convergence on router r{}".format(rtrNum))
164
165 router = tgen.gears["r{}".format(rtrNum)]
166 reffile = os.path.join(CWD, "r{}/bgp_summary.json".format(rtrNum))
167 expected = json.loads(open(reffile).read())
168
169 test_func = functools.partial(
170 topotest.router_json_cmp, router, "show ip bgp summary json", expected
171 )
172 _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
173 assertmsg = "BGP router R{} did not converge".format(rtrNum)
174 assert res is None, assertmsg
175
176 # tgen.mininet_cli()
177
178
179 def get_shut_msg_count(tgen):
180 shuts = {}
181 for rtrNum in [2, 4]:
182 shutmsg = tgen.net["r{}".format(rtrNum)].cmd_nostatus(
183 'grep -c "NOTIFICATION.*Cease/Administrative Shutdown" bgpd.log', warn=False
184 )
185 try:
186 shuts[rtrNum] = int(shutmsg.strip())
187 except ValueError:
188 shuts[rtrNum] = 0
189 return shuts
190
191
192 def test_bgp_shutdown():
193 "Test BGP instance shutdown"
194
195 tgen = get_topogen()
196
197 # Skip if previous fatal error condition is raised
198 if tgen.routers_have_failure():
199 pytest.skip(tgen.errors)
200
201 shuts_before = get_shut_msg_count(tgen)
202
203 tgen.net["r1"].cmd(
204 'vtysh -c "conf t" -c "router bgp 65000" -c "bgp shutdown message ABCDabcd"'
205 )
206
207 # Check BGP Summary on local and remote routers
208 for rtrNum in [1, 2, 4]:
209 logger.info(
210 "Checking BGP Summary after shutdown of R1 BGP on router r{}".format(rtrNum)
211 )
212
213 router = tgen.gears["r{}".format(rtrNum)]
214 reffile = os.path.join(CWD, "r{}/bgp_shutdown_summary.json".format(rtrNum))
215 expected = json.loads(open(reffile).read())
216
217 test_func = functools.partial(
218 topotest.router_json_cmp, router, "show ip bgp summary json", expected
219 )
220 _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
221 assertmsg = "BGP sessions on router R{} are in incorrect state (not down as expected?)".format(
222 rtrNum
223 )
224 assert res is None, assertmsg
225
226 shuts_after = get_shut_msg_count(tgen)
227
228 for k in shuts_before:
229 assert shuts_before[k] + 1 == shuts_after[k]
230
231
232 def test_bgp_shutdown_message():
233 "Test BGP Peer Shutdown Message"
234
235 tgen = get_topogen()
236
237 # Skip if previous fatal error condition is raised
238 if tgen.routers_have_failure():
239 pytest.skip(tgen.errors)
240
241 for rtrNum in [2, 4]:
242 logger.info("Checking BGP shutdown received on router r{}".format(rtrNum))
243
244 shut_message = tgen.net["r{}".format(rtrNum)].cmd(
245 'grep -e "NOTIFICATION.*Cease/Administrative Shutdown.*ABCDabcd" bgpd.log'
246 )
247 assertmsg = "BGP shutdown message not received on router R{}".format(rtrNum)
248 assert shut_message != "", assertmsg
249
250
251 def test_bgp_no_shutdown():
252 "Test BGP instance no shutdown"
253
254 tgen = get_topogen()
255
256 # Skip if previous fatal error condition is raised
257 if tgen.routers_have_failure():
258 pytest.skip(tgen.errors)
259
260 tgen.net["r1"].cmd('vtysh -c "conf t" -c "router bgp 65000" -c "no bgp shutdown"')
261
262 # Check BGP Summary on local and remote routers
263 for rtrNum in [1, 2, 4]:
264 logger.info(
265 "Checking BGP Summary after removing bgp shutdown on router r1 on router r{}".format(
266 rtrNum
267 )
268 )
269
270 router = tgen.gears["r{}".format(rtrNum)]
271 reffile = os.path.join(CWD, "r{}/bgp_summary.json".format(rtrNum))
272 expected = json.loads(open(reffile).read())
273
274 test_func = functools.partial(
275 topotest.router_json_cmp, router, "show ip bgp summary json", expected
276 )
277 _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
278 assertmsg = "BGP sessions on router R{} are in incorrect state (not down as expected?)".format(
279 rtrNum
280 )
281 assert res is None, assertmsg
282
283
284 def test_bgp_metric_config():
285 "Test BGP Changing metric values in route-maps"
286
287 tgen = get_topogen()
288
289 # Skip if previous fatal error condition is raised
290 if tgen.routers_have_failure():
291 pytest.skip(tgen.errors)
292
293 logger.info("Configuring bgp route-maps on router r1 and r2 to update metric")
294
295 # # Adding the following configuration to r1:
296 # router bgp 65000
297 # address-family ipv4 unicast
298 # neighbor 192.168.0.2 route-map addmetric-in in
299 # neighbor 192.168.0.2 route-map addmetric-out out
300 # neighbor 192.168.101.2 route-map setmetric-in in
301 # neighbor 192.168.101.2 route-map setmetric-out out
302 # exit-address-family
303 # !
304 # ip prefix-list net1 seq 10 permit 192.168.101.0/24
305 # ip prefix-list net2 seq 20 permit 192.168.1.0/24
306 # !
307 # route-map setmetric-in permit 10
308 # match ip address prefix-list net1
309 # set metric 111
310 # !
311 # route-map setmetric-in permit 20
312 # !
313 # route-map setmetric-out permit 10
314 # match ip address prefix-list net2
315 # set metric 1011
316 # !
317 # route-map setmetric-out permit 20
318 # !
319 # route-map addmetric-in permit 10
320 # set metric +11
321 # !
322 # route-map addmetric-out permit 10
323 # set metric +12
324 # !
325
326 tgen.net["r1"].cmd(
327 'vtysh -c "conf t" -c "router bgp 65000" '
328 + '-c "address-family ipv4 unicast" '
329 + '-c "neighbor 192.168.0.2 route-map addmetric-in in" '
330 + '-c "neighbor 192.168.0.2 route-map addmetric-out out" '
331 + '-c "neighbor 192.168.101.2 route-map setmetric-in in" '
332 + '-c "neighbor 192.168.101.2 route-map setmetric-out out" '
333 )
334 tgen.net["r1"].cmd(
335 'vtysh -c "conf t" '
336 + '-c "ip prefix-list net1 seq 10 permit 192.168.101.0/24" '
337 + '-c "ip prefix-list net2 seq 20 permit 192.168.1.0/24"'
338 )
339 tgen.net["r1"].cmd(
340 'vtysh -c "conf t" '
341 + '-c "route-map setmetric-in permit 10" '
342 + '-c "match ip address prefix-list net1" '
343 + '-c "set metric 111" '
344 + '-c "route-map setmetric-in permit 20"'
345 )
346 tgen.net["r1"].cmd(
347 'vtysh -c "conf t" '
348 + '-c "route-map setmetric-out permit 10" '
349 + '-c "match ip address prefix-list net2" '
350 + '-c "set metric 1011" '
351 + '-c "route-map setmetric-out permit 20"'
352 )
353 tgen.net["r1"].cmd(
354 'vtysh -c "conf t" '
355 + '-c "route-map addmetric-in permit 10" '
356 + '-c "set metric +11"'
357 )
358 tgen.net["r1"].cmd(
359 'vtysh -c "conf t" '
360 + '-c "route-map addmetric-out permit 10" '
361 + '-c "set metric +12"'
362 )
363
364 # # Adding the following configuration to r2:
365 # router bgp 65000
366 # address-family ipv4 unicast
367 # neighbor 192.168.0.1 route-map subtractmetric-in in
368 # neighbor 192.168.0.1 route-map subtractmetric-out out
369 # neighbor 192.168.201.2 route-map setmetric-in in
370 # neighbor 192.168.201.2 route-map setmetric-out out
371 # exit-address-family
372 # !
373 # ip prefix-list net1 seq 10 permit 192.168.201.0/24
374 # ip prefix-list net2 seq 20 permit 192.168.2.0/24
375 # !
376 # route-map setmetric-in permit 10
377 # match ip address prefix-list net1
378 # set metric 222
379 # !
380 # route-map setmetric-in permit 20
381 # !
382 # route-map setmetric-out permit 10
383 # match ip address prefix-list net2
384 # set metric 2022
385 # !
386 # route-map setmetric-out permit 20
387 # !
388 # route-map subtractmetric-in permit 10
389 # set metric -22
390 # !
391 # route-map subtractmetric-out permit 10
392 # set metric -23
393 # !
394
395 tgen.net["r2"].cmd(
396 'vtysh -c "conf t" -c "router bgp 65000" '
397 + '-c "address-family ipv4 unicast" '
398 + '-c "neighbor 192.168.0.1 route-map subtractmetric-in in" '
399 + '-c "neighbor 192.168.0.1 route-map subtractmetric-out out" '
400 + '-c "neighbor 192.168.201.2 route-map setmetric-in in" '
401 + '-c "neighbor 192.168.201.2 route-map setmetric-out out" '
402 )
403 tgen.net["r2"].cmd(
404 'vtysh -c "conf t" '
405 + '-c "ip prefix-list net1 seq 10 permit 192.168.201.0/24" '
406 + '-c "ip prefix-list net2 seq 20 permit 192.168.2.0/24" '
407 )
408 tgen.net["r2"].cmd(
409 'vtysh -c "conf t" '
410 + '-c "route-map setmetric-in permit 10" '
411 + '-c "match ip address prefix-list net1" '
412 + '-c "set metric 222" '
413 + '-c "route-map setmetric-in permit 20"'
414 )
415 tgen.net["r2"].cmd(
416 'vtysh -c "conf t" '
417 + '-c "route-map setmetric-out permit 10" '
418 + '-c "match ip address prefix-list net2" '
419 + '-c "set metric 2022" '
420 + '-c "route-map setmetric-out permit 20"'
421 )
422 tgen.net["r2"].cmd(
423 'vtysh -c "conf t" '
424 + '-c "route-map subtractmetric-in permit 10" '
425 + '-c "set metric -22"'
426 )
427 tgen.net["r2"].cmd(
428 'vtysh -c "conf t" '
429 + '-c "route-map subtractmetric-out permit 10" '
430 + '-c "set metric -23"'
431 )
432
433 # Clear IN the bgp neighbors to make sure the route-maps are applied
434 tgen.net["r1"].cmd(
435 'vtysh -c "clear ip bgp 192.168.0.2 in" ' + '-c "clear ip bgp 192.168.101.2 in"'
436 )
437 tgen.net["r2"].cmd(
438 'vtysh -c "clear ip bgp 192.168.0.1 in" ' + '-c "clear ip bgp 192.168.201.2 in"'
439 )
440
441 # tgen.mininet_cli()
442
443 # Checking BGP config - should show the bgp metric settings in the route-maps
444 logger.info("Checking BGP configuration for correct 'set metric' values")
445
446 setmetric111 = (
447 tgen.net["r1"].cmd('vtysh -c "show running" | grep "^ set metric 111"').rstrip()
448 )
449 assertmsg = (
450 "'set metric 111' configuration applied to R1, but not visible in configuration"
451 )
452 assert setmetric111 == " set metric 111", assertmsg
453
454 setmetric222 = (
455 tgen.net["r2"].cmd('vtysh -c "show running" | grep "^ set metric 222"').rstrip()
456 )
457 assertmsg = (
458 "'set metric 222' configuration applied to R2, but not visible in configuration"
459 )
460 assert setmetric222 == " set metric 222", assertmsg
461
462
463 def test_bgp_metric_add_config():
464 "Test BGP Changing metric values in route-maps"
465
466 tgen = get_topogen()
467
468 # Skip if previous fatal error condition is raised
469 if tgen.routers_have_failure():
470 pytest.skip(tgen.errors)
471
472 logger.info("Checking BGP configuration for correct 'set metric' ADD value")
473
474 setmetricP11 = (
475 tgen.net["r1"].cmd('vtysh -c "show running" | grep "^ set metric +11"').rstrip()
476 )
477 assertmsg = (
478 "'set metric +11' configuration applied to R1, but not visible in configuration"
479 )
480 assert setmetricP11 == " set metric +11", assertmsg
481
482
483 def test_bgp_metric_subtract_config():
484 "Test BGP Changing metric values in route-maps"
485
486 tgen = get_topogen()
487
488 # Skip if previous fatal error condition is raised
489 if tgen.routers_have_failure():
490 pytest.skip(tgen.errors)
491
492 logger.info("Checking BGP configuration for correct 'set metric' SUBTRACT value")
493
494 setmetricM22 = (
495 tgen.net["r2"].cmd('vtysh -c "show running" | grep "^ set metric -22"').rstrip()
496 )
497 assertmsg = (
498 "'set metric -22' configuration applied to R2, but not visible in configuration"
499 )
500 assert setmetricM22 == " set metric -22", assertmsg
501
502
503 def test_bgp_set_metric():
504 "Test setting metrics"
505
506 tgen = get_topogen()
507
508 # Skip if previous fatal error condition is raised
509 if tgen.routers_have_failure():
510 pytest.skip(tgen.errors)
511
512 logger.info("Test absolute metric")
513
514 # Check BGP Summary on local and remote routers
515 for rtrNum in [1, 2, 4, 5]:
516 logger.info("Checking metrics of BGP router on r{}".format(rtrNum))
517
518 router = tgen.gears["r{}".format(rtrNum)]
519 reffile = os.path.join(CWD, "r{}/show_bgp_metric_test.json".format(rtrNum))
520 expected = json.loads(open(reffile).read())
521
522 test_func = functools.partial(
523 topotest.router_json_cmp, router, "show ip bgp json", expected
524 )
525 _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
526 assertmsg = "BGP metrics on router r{} wrong".format(rtrNum)
527 assert res is None, assertmsg
528
529
530 def test_bgp_remove_metric_rmaps():
531 "Test removing route-maps with metric changes again"
532
533 tgen = get_topogen()
534
535 # Skip if previous fatal error condition is raised
536 if tgen.routers_have_failure():
537 pytest.skip(tgen.errors)
538
539 logger.info("Test absolute metric")
540
541 # Remove metric route-maps and relevant comfiguration
542
543 tgen.net["r1"].cmd(
544 'vtysh -c "conf t" -c "router bgp 65000" '
545 + '-c "address-family ipv4 unicast" '
546 + '-c "no neighbor 192.168.0.2 route-map addmetric-in in" '
547 + '-c "no neighbor 192.168.0.2 route-map addmetric-out out" '
548 + '-c "no neighbor 192.168.101.2 route-map setmetric-in in" '
549 + '-c "no neighbor 192.168.101.2 route-map setmetric-out out" '
550 )
551 tgen.net["r1"].cmd(
552 'vtysh -c "conf t" '
553 + '-c "no ip prefix-list net1" '
554 + '-c "no ip prefix-list net2"'
555 )
556 tgen.net["r1"].cmd('vtysh -c "conf t" ' + '-c "no route-map setmetric-in" ')
557 tgen.net["r1"].cmd('vtysh -c "conf t" ' + '-c "no route-map setmetric-out" ')
558 tgen.net["r1"].cmd('vtysh -c "conf t" ' + '-c "no route-map addmetric-in" ')
559 tgen.net["r1"].cmd('vtysh -c "conf t" ' + '-c "no route-map addmetric-out" ')
560
561 tgen.net["r2"].cmd(
562 'vtysh -c "conf t" -c "router bgp 65000" '
563 + '-c "address-family ipv4 unicast" '
564 + '-c "no neighbor 192.168.0.1 route-map subtractmetric-in in" '
565 + '-c "no neighbor 192.168.0.1 route-map subtractmetric-out out" '
566 + '-c "no neighbor 192.168.201.2 route-map setmetric-in in" '
567 + '-c "no neighbor 192.168.201.2 route-map setmetric-out out" '
568 )
569 tgen.net["r2"].cmd(
570 'vtysh -c "conf t" '
571 + '-c "no ip prefix-list net1" '
572 + '-c "no ip prefix-list net2" '
573 )
574 tgen.net["r2"].cmd('vtysh -c "conf t" ' + '-c "no route-map setmetric-in" ')
575 tgen.net["r2"].cmd('vtysh -c "conf t" ' + '-c "no route-map setmetric-out" ')
576 tgen.net["r2"].cmd('vtysh -c "conf t" ' + '-c "no route-map addmetric-in" ')
577 tgen.net["r2"].cmd('vtysh -c "conf t" ' + '-c "no route-map addmetric-out" ')
578
579 # Clear IN the bgp neighbors to make sure the route-maps are applied
580 tgen.net["r1"].cmd(
581 'vtysh -c "clear ip bgp 192.168.0.2 in" ' + '-c "clear ip bgp 192.168.101.2 in"'
582 )
583 tgen.net["r2"].cmd(
584 'vtysh -c "clear ip bgp 192.168.0.1 in" ' + '-c "clear ip bgp 192.168.201.2 in"'
585 )
586
587 # tgen.mininet_cli()
588
589 # Check BGP Summary on local and remote routers
590 for rtrNum in [1, 2]:
591 logger.info("Checking metrics of BGP router on r{}".format(rtrNum))
592
593 router = tgen.gears["r{}".format(rtrNum)]
594 reffile = os.path.join(CWD, "r{}/show_bgp.json".format(rtrNum))
595 expected = json.loads(open(reffile).read())
596
597 test_func = functools.partial(
598 topotest.router_json_cmp, router, "show ip bgp json", expected
599 )
600 _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
601 assertmsg = "BGP routes on router r{} are wrong after removing metric route-maps".format(
602 rtrNum
603 )
604 assert res is None, assertmsg
605
606
607 def test_bgp_norib():
608 "Test BGP disable RIB (Zebra) Route Install"
609
610 tgen = get_topogen()
611
612 # Skip if previous fatal error condition is raised
613 if tgen.routers_have_failure():
614 pytest.skip(tgen.errors)
615
616 logger.info("Configuring 'bgp no-rib' on router r1")
617
618 tgen.net["r1"].cmd('vtysh -c "conf t" -c "bgp no-rib"')
619
620 # Checking BGP config - should show the "bgp no-rib" under the router bgp section
621 logger.info("Checking BGP configuration for 'bgp no-rib'")
622
623 norib_cfg = (
624 tgen.net["r1"].cmd('vtysh -c "show running bgpd" | grep "^bgp no-rib"').rstrip()
625 )
626
627 assertmsg = "'bgp no-rib' configuration applied, but not visible in configuration"
628 assert norib_cfg == "bgp no-rib", assertmsg
629
630
631 def test_bgp_norib_routes():
632 "Test Routes in Zebra and BGP with the 'bgp-norib' configuration"
633
634 tgen = get_topogen()
635
636 # Skip if previous fatal error condition is raised
637 if tgen.routers_have_failure():
638 pytest.skip(tgen.errors)
639
640 # Checking local BGP routes - they need to be gone from Zebra
641 logger.info("Checking Zebra routes after removing bgp shutdown on router r1")
642
643 router = tgen.gears["r1"]
644 reffile = os.path.join(CWD, "r1/ip_route_norib.json")
645 expected = json.loads(open(reffile).read())
646
647 test_func = functools.partial(
648 topotest.router_json_cmp, router, "show ip route json", expected
649 )
650 _, res = topotest.run_and_expect(test_func, None, count=30, wait=2)
651 assertmsg = "Zebra IPv4 Routes after configuring 'bgp no-rib' (There should be no BGP routes in Zebra anymore)"
652 assert res is None, assertmsg
653
654 # Check BGP Summary on local and remote routers
655 for rtrNum in [1, 2, 4]:
656 logger.info(
657 "Checking BGP Summary after 'bgp no-rib' on router r1 on router r{}".format(
658 rtrNum
659 )
660 )
661
662 router = tgen.gears["r{}".format(rtrNum)]
663 reffile = os.path.join(CWD, "r{}/bgp_summary.json".format(rtrNum))
664 expected = json.loads(open(reffile).read())
665
666 test_func = functools.partial(
667 topotest.router_json_cmp, router, "show ip bgp summary json", expected
668 )
669 _, res = topotest.run_and_expect(test_func, None, count=30, wait=2)
670 assertmsg = "BGP sessions on router R{} has incorrect routes after adding 'bgp no-rib on r1'".format(
671 rtrNum
672 )
673 assert res is None, assertmsg
674
675 # tgen.mininet_cli()
676
677
678 def test_bgp_disable_norib():
679 "Test BGP disabling the no-RIB (Zebra) Route Install"
680
681 tgen = get_topogen()
682
683 # Skip if previous fatal error condition is raised
684 if tgen.routers_have_failure():
685 pytest.skip(tgen.errors)
686
687 logger.info("Configuring 'no bgp no-rib' on router r1")
688
689 tgen.net["r1"].cmd('vtysh -c "conf t" -c "no bgp no-rib"')
690
691 # Checking BGP config - should show the "bgp no-rib" under the router bgp section
692 logger.info("Checking BGP configuration for 'bgp no-rib'")
693
694 norib_cfg = (
695 tgen.net["r1"]
696 .cmd('vtysh -c "show running bgpd" | grep "^ bgp no-rib"')
697 .rstrip()
698 )
699
700 assertmsg = (
701 "'no bgp no-rib'configuration applied, but still visible in configuration"
702 )
703 assert norib_cfg == "", assertmsg
704
705
706 def test_bgp_disable_norib_routes():
707 "Test Routes in Zebra and BGP with the 'bgp-norib' configuration"
708
709 tgen = get_topogen()
710
711 # Skip if previous fatal error condition is raised
712 if tgen.routers_have_failure():
713 pytest.skip(tgen.errors)
714
715 # Checking local BGP routes - they need to be gone from Zebra
716 logger.info("Checking Zebra routes after removing bgp shutdown on router r1")
717
718 router = tgen.gears["r1"]
719 reffile = os.path.join(CWD, "r1/ip_route.json")
720 expected = json.loads(open(reffile).read())
721
722 test_func = functools.partial(
723 topotest.router_json_cmp, router, "show ip route json", expected
724 )
725 _, res = topotest.run_and_expect(test_func, None, count=30, wait=2)
726 assertmsg = "Zebra IPv4 Routes wrong after removing the 'bgp no-rib'"
727 assert res is None, assertmsg
728
729 # Check BGP Summary on local and remote routers
730 for rtrNum in [1, 2, 4]:
731 logger.info(
732 "Checking BGP Summary after removing the 'bgp no-rib' on router r1 on router r{}".format(
733 rtrNum
734 )
735 )
736
737 router = tgen.gears["r{}".format(rtrNum)]
738 reffile = os.path.join(CWD, "r{}/bgp_summary.json".format(rtrNum))
739 expected = json.loads(open(reffile).read())
740
741 test_func = functools.partial(
742 topotest.router_json_cmp, router, "show ip bgp summary json", expected
743 )
744 _, res = topotest.run_and_expect(test_func, None, count=30, wait=2)
745 assertmsg = "BGP sessions on router R{} has incorrect routes after removing 'bgp no-rib on r1'".format(
746 rtrNum
747 )
748 assert res is None, assertmsg
749
750 # tgen.mininet_cli()
751
752
753 def test_bgp_delayopen_without():
754 "Optional test of BGP functionality and behaviour without DelayOpenTimer enabled to establish a reference for following tests"
755 tgen = get_topogen()
756 if tgen.routers_have_failure():
757 pytest.skip(tgen.errors)
758
759 # part 1: no delay r1 <=> no delay r4
760 logger.info(
761 "Starting optional test of BGP functionality without DelayOpenTimer enabled to establish a reference for following tests"
762 )
763
764 # 1.1 enable peering shutdown
765 logger.info("Enable shutdown of peering between r1 and r4")
766 tgen.net["r1"].cmd(
767 'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.2 shutdown"'
768 )
769 tgen.net["r4"].cmd(
770 'vtysh -c "conf t" -c "router bgp 65100" -c "neighbor 192.168.101.1 shutdown"'
771 )
772
773 # 1.2 wait for peers to shut down (poll output)
774 for router_num in [1, 4]:
775 logger.info(
776 "Checking BGP summary after enabling shutdown of peering on r{}".format(
777 router_num
778 )
779 )
780 router = tgen.gears["r{}".format(router_num)]
781 reffile = os.path.join(
782 CWD, "r{}/bgp_delayopen_summary_shutdown.json".format(router_num)
783 )
784 expected = json.loads(open(reffile).read())
785 test_func = functools.partial(
786 topotest.router_json_cmp, router, "show ip bgp summary json", expected
787 )
788 _, res = topotest.run_and_expect(test_func, None, count=5, wait=1)
789 assertmsg = "BGP session on r{} did not shut down peer".format(router_num)
790 assert res is None, assertmsg
791
792 # 1.3 disable peering shutdown
793 logger.info("Disable shutdown of peering between r1 and r4")
794 tgen.net["r1"].cmd(
795 'vtysh -c "conf t" -c "router bgp 65000" -c "no neighbor 192.168.101.2 shutdown"'
796 )
797 tgen.net["r4"].cmd(
798 'vtysh -c "conf t" -c "router bgp 65100" -c "no neighbor 192.168.101.1 shutdown"'
799 )
800
801 # 1.4 wait for peers to establish connection (poll output)
802 for router_num in [1, 4]:
803 logger.info(
804 "Checking BGP summary after disabling shutdown of peering on r{}".format(
805 router_num
806 )
807 )
808 router = tgen.gears["r{}".format(router_num)]
809 reffile = os.path.join(
810 CWD, "r{}/bgp_delayopen_summary_established.json".format(router_num)
811 )
812 expected = json.loads(open(reffile).read())
813 test_func = functools.partial(
814 topotest.router_json_cmp, router, "show ip bgp summary json", expected
815 )
816 _, res = topotest.run_and_expect(test_func, None, count=5, wait=1)
817 assertmsg = (
818 "BGP session on r{} did not establish a connection with peer".format(
819 router_num
820 )
821 )
822 assert res is None, assertmsg
823
824 # tgen.mininet_cli()
825
826 # end test_bgp_delayopen_without
827
828
829 def test_bgp_delayopen_singular():
830 "Test of BGP functionality and behaviour with DelayOpenTimer enabled on one side of the peering"
831
832 tgen = get_topogen()
833 if tgen.routers_have_failure():
834 pytest.skip(tgen.errors)
835
836 # part 2: delay 240s r1 <=> no delay r4
837 logger.info(
838 "Starting test of BGP functionality and behaviour with DelayOpenTimer enabled on one side of the peering"
839 )
840
841 # 2.1 enable peering shutdown
842 logger.info("Enable shutdown of peering between r1 and r4")
843 tgen.net["r1"].cmd(
844 'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.2 shutdown"'
845 )
846 tgen.net["r4"].cmd(
847 'vtysh -c "conf t" -c "router bgp 65100" -c "neighbor 192.168.101.1 shutdown"'
848 )
849
850 # 2.2 wait for peers to shut down (poll output)
851 for router_num in [1, 4]:
852 logger.info(
853 "Checking BGP summary after disabling shutdown of peering on r{}".format(
854 router_num
855 )
856 )
857 router = tgen.gears["r{}".format(router_num)]
858 reffile = os.path.join(
859 CWD, "r{}/bgp_delayopen_summary_shutdown.json".format(router_num)
860 )
861 expected = json.loads(open(reffile).read())
862 test_func = functools.partial(
863 topotest.router_json_cmp, router, "show ip bgp summary json", expected
864 )
865 _, res = topotest.run_and_expect(test_func, None, count=5, wait=1)
866 assertmsg = "BGP session on r{} did not shut down peer".format(router_num)
867 assert res is None, assertmsg
868
869 # 2.3 set delayopen on R1 to 240
870 logger.info("Setting DelayOpenTime for neighbor r4 to 240 seconds on r1")
871 tgen.net["r1"].cmd(
872 'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.2 timers delayopen 240"'
873 )
874
875 # 2.4 check config (poll output)
876 logger.info("Checking BGP neighbor configuration after setting DelayOpenTime on r1")
877 router = tgen.gears["r1"]
878 reffile = os.path.join(CWD, "r1/bgp_delayopen_neighbor.json")
879 expected = json.loads(open(reffile).read())
880 test_func = functools.partial(
881 topotest.router_json_cmp, router, "show bgp neighbors json", expected
882 )
883 _, res = topotest.run_and_expect(test_func, None, count=5, wait=1)
884 assertmsg = "BGP session on r1 failed to set DelayOpenTime for r4"
885 assert res is None, assertmsg
886
887 # 2.5 disable peering shutdown
888 logger.info("Disable shutdown of peering between r1 and r4")
889 tgen.net["r1"].cmd(
890 'vtysh -c "conf t" -c "router bgp 65000" -c "no neighbor 192.168.101.2 shutdown"'
891 )
892 tgen.net["r4"].cmd(
893 'vtysh -c "conf t" -c "router bgp 65100" -c "no neighbor 192.168.101.1 shutdown"'
894 )
895
896 # 2.6 wait for peers to establish connection (poll output)
897 for router_num in [1, 4]:
898 logger.info(
899 "Checking BGP summary after disabling shutdown of peering on r{}".format(
900 router_num
901 )
902 )
903 router = tgen.gears["r{}".format(router_num)]
904 reffile = os.path.join(
905 CWD, "r{}/bgp_delayopen_summary_established.json".format(router_num)
906 )
907 expected = json.loads(open(reffile).read())
908 test_func = functools.partial(
909 topotest.router_json_cmp, router, "show ip bgp summary json", expected
910 )
911 _, res = topotest.run_and_expect(test_func, None, count=5, wait=1)
912 assertmsg = (
913 "BGP session on r{} did not establish a connection with peer".format(
914 router_num
915 )
916 )
917 assert res is None, assertmsg
918
919 # 2.7 unset delayopen on R1
920 logger.info("Disabling DelayOpenTimer for neighbor r4 on r1")
921 tgen.net["r1"].cmd(
922 'vtysh -c "conf t" -c "router bgp 65000" -c "no neighbor 192.168.101.2 timers delayopen"'
923 )
924
925 # 2.8 check config (poll output)
926 logger.info(
927 "Checking BGP neighbor configuration after disabling DelayOpenTimer on r1"
928 )
929 delayopen_cfg = (
930 tgen.net["r1"]
931 .cmd('vtysh -c "show bgp neighbors json" | grep "DelayOpenTimeMsecs"')
932 .rstrip()
933 )
934 assertmsg = "BGP session on r1 failed disable DelayOpenTimer for peer r4"
935 assert delayopen_cfg == "", assertmsg
936
937 # tgen.mininet_cli()
938
939 # end test_bgp_delayopen_singular
940
941
942 def test_bgp_delayopen_dual():
943 "Test of BGP functionality and behaviour with DelayOpenTimer enabled on both sides of the peering with different timer intervals"
944 tgen = get_topogen()
945 if tgen.routers_have_failure():
946 pytest.skip(tgen.errors)
947
948 # part 3: delay 60s R2 <=> delay 30s R5
949 logger.info(
950 "Starting test of BGP functionality and behaviour with DelayOpenTimer enabled on both sides of the peering with different timer intervals"
951 )
952
953 # 3.1 enable peering shutdown
954 logger.info("Enable shutdown of peering between r2 and r5")
955 tgen.net["r2"].cmd(
956 'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.201.2 shutdown"'
957 )
958 tgen.net["r5"].cmd(
959 'vtysh -c "conf t" -c "router bgp 65200" -c "neighbor 192.168.201.1 shutdown"'
960 )
961
962 # 3.2 wait for peers to shut down (pool output)
963 for router_num in [2, 5]:
964 logger.info(
965 "Checking BGP summary after disabling shutdown of peering on r{}".format(
966 router_num
967 )
968 )
969 router = tgen.gears["r{}".format(router_num)]
970 reffile = os.path.join(
971 CWD, "r{}/bgp_delayopen_summary_shutdown.json".format(router_num)
972 )
973 expected = json.loads(open(reffile).read())
974 test_func = functools.partial(
975 topotest.router_json_cmp, router, "show ip bgp summary json", expected
976 )
977 _, res = topotest.run_and_expect(test_func, None, count=5, wait=1)
978 assertmsg = "BGP session on r{} did not shut down peer".format(router_num)
979 assert res is None, assertmsg
980
981 # 3.3 set delayopen on R2 to 60s and on R5 to 30s
982 logger.info("Setting DelayOpenTime for neighbor r5 to 60 seconds on r2")
983 tgen.net["r2"].cmd(
984 'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.201.2 timers delayopen 60"'
985 )
986 logger.info("Setting DelayOpenTime for neighbor r2 to 30 seconds on r5")
987 tgen.net["r5"].cmd(
988 'vtysh -c "conf t" -c "router bgp 65200" -c "neighbor 192.168.201.1 timers delayopen 30"'
989 )
990
991 # 3.4 check config (poll output)
992 for router_num in [2, 5]:
993 logger.info(
994 "Checking BGP neighbor configuration after setting DelayOpenTime on r{}i".format(
995 router_num
996 )
997 )
998 router = tgen.gears["r{}".format(router_num)]
999 reffile = os.path.join(
1000 CWD, "r{}/bgp_delayopen_neighbor.json".format(router_num)
1001 )
1002 expected = json.loads(open(reffile).read())
1003 test_func = functools.partial(
1004 topotest.router_json_cmp, router, "show bgp neighbors json", expected
1005 )
1006 _, res = topotest.run_and_expect(test_func, None, count=5, wait=1)
1007 assertmsg = "BGP session on r{} failed to set DelayOpenTime".format(router_num)
1008 assert res is None, assertmsg
1009
1010 ## 3.5 disable peering shutdown
1011 logger.info("Disable shutdown of peering between r2 and r5")
1012 tgen.net["r2"].cmd(
1013 'vtysh -c "conf t" -c "router bgp 65000" -c "no neighbor 192.168.201.2 shutdown"'
1014 )
1015 tgen.net["r5"].cmd(
1016 'vtysh -c "conf t" -c "router bgp 65200" -c "no neighbor 192.168.201.1 shutdown"'
1017 )
1018
1019 ## 3.6 wait for peers to reach connect or active state (poll output)
1020 delay_start = int(time.time())
1021 for router_num in [2, 5]:
1022 logger.info(
1023 "Checking BGP summary after disabling shutdown of peering on r{}".format(
1024 router_num
1025 )
1026 )
1027 router = tgen.gears["r{}".format(router_num)]
1028 reffile = os.path.join(
1029 CWD, "r{}/bgp_delayopen_summary_connect.json".format(router_num)
1030 )
1031 expected = json.loads(open(reffile).read())
1032 test_func = functools.partial(
1033 topotest.router_json_cmp, router, "show ip bgp summary json", expected
1034 )
1035 _, res = topotest.run_and_expect(test_func, None, count=5, wait=1)
1036 assertmsg = "BGP session on r{} did not enter Connect state with peer".format(
1037 router_num
1038 )
1039 assert res is None, assertmsg
1040
1041 ## 3.7 wait for peers to establish connection (poll output)
1042 for router_num in [2, 5]:
1043 logger.info(
1044 "Checking BGP summary after disabling shutdown of peering on r{}".format(
1045 router_num
1046 )
1047 )
1048 router = tgen.gears["r{}".format(router_num)]
1049 reffile = os.path.join(
1050 CWD, "r{}/bgp_delayopen_summary_established.json".format(router_num)
1051 )
1052 expected = json.loads(open(reffile).read())
1053 test_func = functools.partial(
1054 topotest.router_json_cmp, router, "show ip bgp summary json", expected
1055 )
1056 _, res = topotest.run_and_expect(test_func, None, count=35, wait=1)
1057 assertmsg = (
1058 "BGP session on r{} did not establish a connection with peer".format(
1059 router_num
1060 )
1061 )
1062 assert res is None, assertmsg
1063
1064 delay_stop = int(time.time())
1065 assertmsg = "BGP peering between r2 and r5 was established before DelayOpenTimer (30sec) on r2 could expire"
1066 assert (delay_stop - delay_start) > 30, assertmsg
1067
1068 # 3.8 unset delayopen on R2 and R5
1069 logger.info("Disabling DelayOpenTimer for neighbor r5 on r2")
1070 tgen.net["r2"].cmd(
1071 'vtysh -c "conf t" -c "router bgp 65000" -c "no neighbor 192.168.201.2 timers delayopen"'
1072 )
1073 logger.info("Disabling DelayOpenTimer for neighbor r2 on r5")
1074 tgen.net["r5"].cmd(
1075 'vtysh -c "conf t" -c "router bgp 65200" -c "no neighbor 192.168.201.1 timers delayopen"'
1076 )
1077
1078 # 3.9 check config (poll output)
1079 for router_num in [2, 5]:
1080 logger.info(
1081 "Checking BGP neighbor configuration after disabling DelayOpenTimer on r{}".format(
1082 router_num
1083 )
1084 )
1085 delayopen_cfg = (
1086 tgen.net["r{}".format(router_num)]
1087 .cmd('vtysh -c "show bgp neighbors json" | grep "DelayOpenTimeMsecs"')
1088 .rstrip()
1089 )
1090 assertmsg = "BGP session on r{} failed disable DelayOpenTimer".format(
1091 router_num
1092 )
1093 assert delayopen_cfg == "", assertmsg
1094
1095 # tgen.mininet_cli()
1096
1097 # end test_bgp_delayopen_dual
1098
1099
1100 if __name__ == "__main__":
1101 args = ["-s"] + sys.argv[1:]
1102 sys.exit(pytest.main(args))