]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-2.py
Merge pull request #9940 from pguibert6WIND/misc_topotests
[mirror_frr.git] / tests / topotests / bgp_gr_functionality_topo2 / test_bgp_gr_functionality_topo2-2.py
1 #!/usr/bin/env python
2 #
3 # Copyright (c) 2019 by VMware, Inc. ("VMware")
4 # Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF")
5 # in this file.
6 #
7 # Permission to use, copy, modify, and/or distribute this software
8 # for any purpose with or without fee is hereby granted, provided
9 # that the above copyright notice and this permission notice appear
10 # in all copies.
11 #
12 # THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
13 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
15 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
16 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
17 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
18 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
19 # OF THIS SOFTWARE.
20 #
21
22 """
23 Following tests are covered to test BGP Graceful Restart functionality.
24 Basic Common Test steps for all the test case below :
25 - Create topology (setup module)
26 Creating 7 routers topology
27 - Bring up topology
28 - Verify for bgp to converge
29 - Configure BGP Graceful Restart on both the routers.
30
31 TC_1_2:
32 Verify that EOR message is sent out only after initial convergence
33 Verify whether EOR message is received from all the peers after restart
34 TC_3:
35 Verify the selection deferral timer functionality when EOR is not sent
36 by the helper router
37 TC_11:
38 Verify that selection-deferral timer sets the maximum time to
39 avoid deadlock during which the best-path
40 TC_10:
41 Test Objective : Test GR scenarios on helper router by enabling
42 Graceful Restart for multiple address families.
43 TC_15:
44 Test Objective : Test GR scenarios by enabling Graceful Restart
45 for multiple address families..
46 TC_16:
47 Test Objective : Verify BGP-GR feature when restarting node
48 is a transit router for it's iBGP peers.
49 TC_18:
50 Test Objective : Verify that GR helper router deletes stale routes
51 received from restarting node, if GR capability is not present in
52 TC_19:
53 Test Objective : Verify that GR routers keeps all the routes
54 received from restarting node if both the routers are
55 TC_26:
56 Test Objective : Test GR scenarios on helper router by enabling
57 Graceful Restart for multiple address families.
58 TC_28:
59 Test Objective : Verify if helper node goes down before restarting
60 node comes up online, helper node sets the R-bit to avoid dead-lock
61 TC_29:
62 Test Objective : Change timers on the fly, and
63 verify if it takes immediate effect.
64 TC_33:
65 Test Objective : Helper router receives same prefixes from two
66 different routers (GR-restarting and GR-disabled). Keeps the
67 TC_34_1:
68 Test Objective : Restarting node doesn't preserve forwarding
69 state, helper router should not keep the stale entries.
70 TC_34_2:
71 Test Objective : Restarting node doesn't preserve the forwarding
72 state verify the behaviour on helper node, if it still keeps the
73 TC_32:
74 Test Objective : Restarting node is connected to multiple helper
75 nodes, one of them doesn't send EOR to restarting router. Verify
76 TC_37:
77 Test Objective : Verify if helper node restarts before sending the
78 EOR message, restarting node doesn't wait until stale path timer
79 TC_30:
80 Test Objective : Restarting node removes stale routes from Zebra
81 after receiving an EOR from helper router.
82
83 """
84
85 import os
86 import sys
87 import time
88 import pytest
89 from time import sleep
90
91 # Save the Current Working Directory to find configuration files.
92 CWD = os.path.dirname(os.path.realpath(__file__))
93 sys.path.append(os.path.join("../"))
94 sys.path.append(os.path.join("../lib/"))
95
96 # pylint: disable=C0413
97 # Import topogen and topotest helpers
98 from lib.topogen import Topogen, get_topogen
99 from lib.topolog import logger
100
101 # Required to instantiate the topology builder class.
102
103 # Import topoJson from lib, to create topology and initial configuration
104 from lib.topojson import build_config_from_json
105 from lib.bgp import (
106 clear_bgp,
107 verify_bgp_rib,
108 verify_graceful_restart,
109 create_router_bgp,
110 verify_r_bit,
111 verify_eor,
112 verify_f_bit,
113 verify_bgp_convergence,
114 verify_gr_address_family,
115 modify_bgp_config_when_bgpd_down,
116 verify_graceful_restart_timers,
117 verify_bgp_convergence_from_running_config,
118 )
119
120 from lib.common_config import (
121 write_test_header,
122 reset_config_on_routers,
123 start_topology,
124 kill_router_daemons,
125 start_router_daemons,
126 verify_rib,
127 check_address_types,
128 write_test_footer,
129 check_router_status,
130 step,
131 get_frr_ipv6_linklocal,
132 required_linux_kernel_version,
133 )
134
135 pytestmark = [pytest.mark.bgpd]
136
137
138 # Global variables
139 BGP_CONVERGENCE = False
140 GR_RESTART_TIMER = 5
141 GR_SELECT_DEFER_TIMER = 5
142 GR_STALEPATH_TIMER = 5
143 PREFERRED_NEXT_HOP = "link_local"
144 NEXT_HOP_4 = ["192.168.1.1", "192.168.4.2"]
145 NEXT_HOP_6 = ["fd00:0:0:1::1", "fd00:0:0:4::2"]
146
147
148 def setup_module(mod):
149 """
150 Sets up the pytest environment
151
152 * `mod`: module name
153 """
154
155 # Required linux kernel version for this suite to run.
156 result = required_linux_kernel_version("4.16")
157 if result is not True:
158 pytest.skip("Kernel requirements are not met")
159
160 global ADDR_TYPES
161
162 testsuite_run_time = time.asctime(time.localtime(time.time()))
163 logger.info("Testsuite start time: {}".format(testsuite_run_time))
164 logger.info("=" * 40)
165
166 logger.info("Running setup_module to create topology")
167
168 # This function initiates the topology build with Topogen...
169 json_file = "{}/bgp_gr_topojson_topo2.json".format(CWD)
170 tgen = Topogen(json_file, mod.__name__)
171 global topo
172 topo = tgen.json_topo
173 # ... and here it calls Mininet initialization functions.
174
175 # Starting topology, create tmp files which are loaded to routers
176 # to start deamons and then start routers
177 start_topology(tgen)
178
179 # Creating configuration from JSON
180 build_config_from_json(tgen, topo)
181
182 # Api call verify whether BGP is converged
183 ADDR_TYPES = check_address_types()
184
185 for addr_type in ADDR_TYPES:
186 BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
187 assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format(
188 BGP_CONVERGENCE
189 )
190
191 logger.info("Running setup_module() done")
192
193
194 def teardown_module(mod):
195 """
196 Teardown the pytest environment
197
198 * `mod`: module name
199 """
200
201 logger.info("Running teardown_module to delete topology")
202
203 tgen = get_topogen()
204
205 # Stop toplogy and Remove tmp files
206 tgen.stop_topology()
207
208 logger.info(
209 "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
210 )
211 logger.info("=" * 40)
212
213
214 def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
215 """
216 This function groups the repetitive function calls into one function.
217 """
218
219 logger.info("configure_gr_followed_by_clear: dut %s peer %s", dut, peer)
220
221 result = create_router_bgp(tgen, topo, input_dict)
222 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
223
224 for addr_type in ADDR_TYPES:
225 neighbor = topo["routers"][peer]["links"][dut][addr_type].split("/")[0]
226 clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
227
228 for addr_type in ADDR_TYPES:
229 neighbor = topo["routers"][dut]["links"][peer][addr_type].split("/")[0]
230 clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
231
232 result = verify_bgp_convergence_from_running_config(tgen)
233 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
234
235 return True
236
237
238 def next_hop_per_address_family(tgen, dut, peer, addr_type, next_hop_dict):
239 """
240 This function returns link_local or global next_hop per address-family
241 """
242
243 intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"]
244 if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
245 next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
246 else:
247 next_hop = next_hop_dict[addr_type]
248
249 return next_hop
250
251
252 def test_BGP_GR_26_p2(request):
253 """
254 Test Objective : Test GR scenarios on helper router by enabling
255 Graceful Restart for multiple address families.
256 """
257
258 tgen = get_topogen()
259 tc_name = request.node.name
260 write_test_header(tc_name)
261
262 # Check router status
263 check_router_status(tgen)
264
265 # Don't run this test if we have any failure.
266 if tgen.routers_have_failure():
267 pytest.skip(tgen.errors)
268
269 # Creating configuration from JSON
270 reset_config_on_routers(tgen)
271
272 logger.info(
273 "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] initialized"
274 )
275
276 # Configure graceful-restart
277 input_dict = {
278 "r1": {
279 "bgp": {
280 "address_family": {
281 "ipv4": {
282 "unicast": {
283 "neighbor": {
284 "r3": {
285 "dest_link": {
286 "r1": {
287 "graceful-restart": True,
288 "next_hop_self": True,
289 "activate": "ipv6",
290 }
291 }
292 }
293 }
294 }
295 },
296 "ipv6": {
297 "unicast": {
298 "neighbor": {
299 "r3": {
300 "dest_link": {
301 "r1": {
302 "graceful-restart": True,
303 "next_hop_self": True,
304 "activate": "ipv4",
305 }
306 }
307 }
308 }
309 }
310 },
311 }
312 }
313 },
314 "r3": {
315 "bgp": {
316 "address_family": {
317 "ipv4": {
318 "unicast": {
319 "neighbor": {
320 "r1": {
321 "dest_link": {
322 "r3": {
323 "graceful-restart-helper": True,
324 "activate": "ipv6",
325 }
326 }
327 }
328 }
329 }
330 },
331 "ipv6": {
332 "unicast": {
333 "neighbor": {
334 "r1": {
335 "dest_link": {
336 "r3": {
337 "graceful-restart-helper": True,
338 "activate": "ipv4",
339 }
340 }
341 }
342 }
343 }
344 },
345 }
346 }
347 },
348 }
349
350 configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
351
352 for addr_type in ADDR_TYPES:
353 result = verify_graceful_restart(
354 tgen, topo, addr_type, input_dict, dut="r3", peer="r1"
355 )
356 assert result is True, "Testcase {} : Failed \n Error {}".format(
357 tc_name, result
358 )
359
360 # Verifying BGP RIB routes
361 dut = "r3"
362 input_topo = {key: topo["routers"][key] for key in ["r1"]}
363 result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
364 assert result is True, "Testcase {} : Failed \n Error {}".format(
365 tc_name, result
366 )
367
368 # Verifying RIB routes before shutting down BGPd daemon
369 result = verify_rib(tgen, addr_type, dut, input_topo)
370 assert result is True, "Testcase {} : Failed \n Error {}".format(
371 tc_name, result
372 )
373
374 # Kill BGPd daemon on R1
375 kill_router_daemons(tgen, "r1", ["bgpd"])
376
377 for addr_type in ADDR_TYPES:
378 # Verifying BGP RIB routes
379 input_topo = {key: topo["routers"][key] for key in ["r1"]}
380 result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
381 assert result is True, "Testcase {} : Failed \n Error {}".format(
382 tc_name, result
383 )
384
385 # Verifying RIB routes before shutting down BGPd daemon
386 result = verify_rib(tgen, addr_type, dut, input_topo)
387 assert result is True, "Testcase {} : Failed \n Error {}".format(
388 tc_name, result
389 )
390
391 # Start BGPd daemon on R1
392 start_router_daemons(tgen, "r1", ["bgpd"])
393
394 for addr_type in ADDR_TYPES:
395 # Verifying BGP RIB routes
396 input_topo = {key: topo["routers"][key] for key in ["r1"]}
397 result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
398 assert result is True, "Testcase {} : Failed \n Error {}".format(
399 tc_name, result
400 )
401
402 # Verifying RIB routes before shutting down BGPd daemon
403 result = verify_rib(tgen, addr_type, dut, input_topo)
404 assert result is True, "Testcase {} : Failed \n Error {}".format(
405 tc_name, result
406 )
407
408 # verify multi address family
409 result = verify_gr_address_family(
410 tgen,
411 topo,
412 addr_type,
413 "ipv4Unicast",
414 dut="r1",
415 peer="r3",
416 )
417 assert result is True, "Testcase {} : Failed \n Error {}".format(
418 tc_name, result
419 )
420
421 # verify multi address family
422 result = verify_gr_address_family(
423 tgen,
424 topo,
425 addr_type,
426 "ipv6Unicast",
427 dut="r1",
428 peer="r3",
429 )
430 assert result is True, "Testcase {} : Failed \n Error {}".format(
431 tc_name, result
432 )
433
434 # verify multi address family
435 result = verify_gr_address_family(
436 tgen,
437 topo,
438 addr_type,
439 "ipv4Unicast",
440 dut="r3",
441 peer="r1",
442 )
443 assert result is True, "Testcase {} : Failed \n Error {}".format(
444 tc_name, result
445 )
446
447 # verify multi address family
448 result = verify_gr_address_family(
449 tgen,
450 topo,
451 addr_type,
452 "ipv6Unicast",
453 dut="r3",
454 peer="r1",
455 )
456 assert result is True, "Testcase {} : Failed \n Error {}".format(
457 tc_name, result
458 )
459
460 write_test_footer(tc_name)
461
462
463 def test_BGP_GR_chaos_28_p1(request):
464 """
465 Test Objective : Verify if helper node goes down before restarting
466 node comes up online, helper node sets the R-bit to avoid dead-lock
467 till SDT expiry.
468 """
469
470 tgen = get_topogen()
471 tc_name = request.node.name
472 write_test_header(tc_name)
473
474 # Check router status
475 check_router_status(tgen)
476
477 # Don't run this test if we have any failure.
478 if tgen.routers_have_failure():
479 pytest.skip(tgen.errors)
480
481 # Creating configuration from JSON
482 reset_config_on_routers(tgen)
483
484 logger.info(
485 "Test Case: test_BGP_GR_chaos_28 :"
486 "[Helper Mode]R3-----R1[Restart Mode] initialized"
487 )
488
489 # Configure graceful-restart
490 input_dict = {
491 "r1": {
492 "bgp": {
493 "address_family": {
494 "ipv4": {
495 "unicast": {
496 "neighbor": {
497 "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
498 }
499 }
500 },
501 "ipv6": {
502 "unicast": {
503 "neighbor": {
504 "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
505 }
506 }
507 },
508 }
509 }
510 },
511 "r3": {
512 "bgp": {
513 "address_family": {
514 "ipv4": {
515 "unicast": {
516 "neighbor": {
517 "r1": {
518 "dest_link": {
519 "r3": {"graceful-restart-helper": True}
520 }
521 }
522 }
523 }
524 },
525 "ipv6": {
526 "unicast": {
527 "neighbor": {
528 "r1": {
529 "dest_link": {
530 "r3": {"graceful-restart-helper": True}
531 }
532 }
533 }
534 }
535 },
536 }
537 }
538 },
539 }
540
541 configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
542
543 for addr_type in ADDR_TYPES:
544 result = verify_graceful_restart(
545 tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
546 )
547 assert result is True, "Testcase {} : Failed \n Error {}".format(
548 tc_name, result
549 )
550
551 logger.info("[Step 1] : Kill BGPd daemon on R1..")
552
553 # Kill BGPd daemon on R1
554 kill_router_daemons(tgen, "r1", ["bgpd"])
555
556 logger.info("[Step 2] : Kill BGPd daemon on R3..")
557
558 # Kill BGPd daemon on R3
559 kill_router_daemons(tgen, "r3", ["bgpd"])
560
561 logger.info("[Step 3] : Start BGPd daemon on R1..")
562
563 # Start BGPd daemon on R1
564 start_router_daemons(tgen, "r1", ["bgpd"])
565
566 logger.info("[Step 4] : Start BGPd daemon on R3..")
567
568 # Start BGPd daemon on R3
569 start_router_daemons(tgen, "r3", ["bgpd"])
570
571 # Verify r_bit
572 for addr_type in ADDR_TYPES:
573 result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r3", peer="r1")
574 assert result is True, "Testcase {} : Failed \n Error {}".format(
575 tc_name, result
576 )
577
578 write_test_footer(tc_name)
579
580
581 def test_BGP_GR_chaos_29_p1(request):
582 """
583 Test Objective : Change timers on the fly, and
584 verify if it takes immediate effect.
585 """
586
587 tgen = get_topogen()
588 tc_name = request.node.name
589 write_test_header(tc_name)
590
591 # Check router status
592 check_router_status(tgen)
593
594 # Don't run this test if we have any failure.
595 if tgen.routers_have_failure():
596 pytest.skip(tgen.errors)
597
598 # Creating configuration from JSON
599 reset_config_on_routers(tgen)
600
601 logger.info(
602 " Test Case : test_BGP_GR_chaos_29"
603 " BGP GR [Helper Mode]R3-----R1[Restart Mode]"
604 " and [restart-time 150]R1 initialized"
605 )
606
607 # Configure graceful-restart and timers
608 input_dict = {
609 "r1": {
610 "bgp": {
611 "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER}},
612 "address_family": {
613 "ipv4": {
614 "unicast": {
615 "neighbor": {
616 "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
617 }
618 }
619 },
620 "ipv6": {
621 "unicast": {
622 "neighbor": {
623 "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
624 }
625 }
626 },
627 },
628 }
629 },
630 "r3": {
631 "bgp": {
632 "address_family": {
633 "ipv4": {
634 "unicast": {
635 "neighbor": {
636 "r1": {
637 "dest_link": {
638 "r3": {"graceful-restart-helper": True}
639 }
640 }
641 }
642 }
643 },
644 "ipv6": {
645 "unicast": {
646 "neighbor": {
647 "r1": {
648 "dest_link": {
649 "r3": {"graceful-restart-helper": True}
650 }
651 }
652 }
653 }
654 },
655 }
656 }
657 },
658 }
659
660 configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
661
662 for addr_type in ADDR_TYPES:
663 result = verify_graceful_restart(
664 tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
665 )
666 assert result is True, "Testcase {} : Failed \n Error {}".format(
667 tc_name, result
668 )
669
670 # Verify graceful-restart timers
671 input_dict_2 = {
672 "r1": {
673 "bgp": {
674 "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER + 5}}
675 }
676 }
677 }
678
679 result = create_router_bgp(tgen, topo, input_dict_2)
680 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
681
682 for addr_type in ADDR_TYPES:
683 input_dict_2 = {
684 "r1": {
685 "bgp": {
686 "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER}}
687 }
688 }
689 }
690
691 result = verify_graceful_restart_timers(
692 tgen, topo, addr_type, input_dict_2, dut="r3", peer="r1"
693 )
694 assert result is True, "Testcase {} : Failed \n Error {}".format(
695 tc_name, result
696 )
697
698 for addr_type in ADDR_TYPES:
699 # Verifying BGP RIB routes before shutting down BGPd daemon
700 dut = "r3"
701 input_dict = {key: topo["routers"][key] for key in ["r1"]}
702 result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
703 assert result is True, "Testcase {} : Failed \n Error {}".format(
704 tc_name, result
705 )
706
707 # Verifying RIB routes before shutting down BGPd daemon
708 result = verify_rib(tgen, addr_type, dut, input_dict)
709 assert result is True, "Testcase {} : Failed \n Error {}".format(
710 tc_name, result
711 )
712
713 logger.info("[Step 2] : Kill BGPd daemon on R1..")
714
715 # Kill BGPd daemon on R1
716 kill_router_daemons(tgen, "r1", ["bgpd"])
717
718 logger.info("[Step 3] : Wait for {} seconds..".format(GR_RESTART_TIMER))
719
720 # Waiting for GR_RESTART_TIMER
721 sleep(GR_RESTART_TIMER)
722
723 for addr_type in ADDR_TYPES:
724 # Verifying BGP RIB routes before shutting down BGPd daemon
725 input_dict = {key: topo["routers"][key] for key in ["r1"]}
726 result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
727 assert result is not True, (
728 "Testcase {} : Failed \n "
729 "r3: routes are still present in BGP RIB\n Error: {}".format(
730 tc_name, result
731 )
732 )
733 logger.info(" Expected behavior: {}".format(result))
734
735 # Verifying RIB routes before shutting down BGPd daemon
736 result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
737 assert result is not True, (
738 "Testcase {} : Failed \n "
739 "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
740 )
741 logger.info(" Expected behavior: {}".format(result))
742
743 logger.info("[Step 4] : Start BGPd daemon on R1..")
744
745 # Start BGPd daemon on R1
746 start_router_daemons(tgen, "r1", ["bgpd"])
747
748 write_test_footer(tc_name)
749
750
751 def test_BGP_GR_chaos_33_p1(request):
752 """
753 Test Objective : Helper router receives same prefixes from two
754 different routers (GR-restarting and GR-disabled). Keeps the
755 stale entry only for GR-restarting node(next-hop is correct).
756 """
757
758 tgen = get_topogen()
759 tc_name = request.node.name
760 write_test_header(tc_name)
761
762 # Check router status
763 check_router_status(tgen)
764
765 # Don't run this test if we have any failure.
766 if tgen.routers_have_failure():
767 pytest.skip(tgen.errors)
768
769 # Creating configuration from JSON
770 reset_config_on_routers(tgen)
771
772 logger.info(
773 " Test Case : test_BGP_GR_chaos_33 "
774 "BGP GR "
775 "[Restart Mode]R1--R3[Helper Mode]--R4[Disabled Mode]"
776 )
777
778 # Configure graceful-restart
779 input_dict = {
780 "r1": {
781 "bgp": {
782 "address_family": {
783 "ipv4": {
784 "unicast": {
785 "neighbor": {
786 "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
787 }
788 }
789 },
790 "ipv6": {
791 "unicast": {
792 "neighbor": {
793 "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
794 }
795 }
796 },
797 }
798 }
799 },
800 "r3": {
801 "bgp": {
802 "address_family": {
803 "ipv4": {
804 "unicast": {
805 "neighbor": {
806 "r1": {
807 "dest_link": {
808 "r3": {"graceful-restart-helper": True}
809 }
810 }
811 }
812 }
813 },
814 "ipv6": {
815 "unicast": {
816 "neighbor": {
817 "r1": {
818 "dest_link": {
819 "r3": {"graceful-restart-helper": True}
820 }
821 }
822 }
823 }
824 },
825 }
826 }
827 },
828 "r4": {
829 "bgp": {
830 "address_family": {
831 "ipv4": {
832 "unicast": {
833 "neighbor": {
834 "r3": {
835 "dest_link": {
836 "r4": {"graceful-restart-disable": True}
837 }
838 }
839 }
840 }
841 },
842 "ipv6": {
843 "unicast": {
844 "neighbor": {
845 "r3": {
846 "dest_link": {
847 "r4": {"graceful-restart-disable": True}
848 }
849 }
850 }
851 }
852 },
853 }
854 }
855 },
856 }
857
858 configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
859
860 for addr_type in ADDR_TYPES:
861 result = verify_graceful_restart(
862 tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
863 )
864 assert result is True, "Testcase {} : Failed \n Error {}".format(
865 tc_name, result
866 )
867
868 logger.info("[Step 2] : Advertise same networks from R1 and R4..")
869
870 # Api call to delete advertised networks
871 input_dict_2 = {
872 "r1": {
873 "bgp": {
874 "address_family": {
875 "ipv4": {
876 "unicast": {
877 "advertise_networks": [
878 {
879 "network": "200.0.20.1/32",
880 "no_of_network": 2,
881 }
882 ]
883 }
884 },
885 "ipv6": {
886 "unicast": {
887 "advertise_networks": [
888 {"network": "2001::1/128", "no_of_network": 2}
889 ]
890 }
891 },
892 }
893 }
894 },
895 "r4": {
896 "bgp": {
897 "address_family": {
898 "ipv4": {
899 "unicast": {
900 "advertise_networks": [
901 {"network": "200.0.20.1/32", "no_of_network": 2}
902 ]
903 }
904 },
905 "ipv6": {
906 "unicast": {
907 "advertise_networks": [
908 {"network": "2001::1/128", "no_of_network": 2}
909 ]
910 }
911 },
912 }
913 }
914 },
915 }
916
917 result = create_router_bgp(tgen, topo, input_dict_2)
918 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
919
920 for addr_type in ADDR_TYPES:
921 # Verifying RIB routes
922 dut = "r3"
923 peer1 = "r1"
924 peer2 = "r4"
925 intf1 = topo["routers"][peer1]["links"][dut]["interface"]
926 intf2 = topo["routers"][peer2]["links"][dut]["interface"]
927
928 if addr_type == "ipv4":
929 next_hop_4 = NEXT_HOP_4
930 result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_4)
931 assert result is True, "Testcase {} : Failed \n Error {}".format(
932 tc_name, result
933 )
934
935 if addr_type == "ipv6":
936 if "link_local" in PREFERRED_NEXT_HOP:
937 next_hop1 = get_frr_ipv6_linklocal(tgen, peer1, intf=intf1)
938 next_hop2 = get_frr_ipv6_linklocal(tgen, peer2, intf=intf2)
939
940 next_hop_6 = [next_hop1, next_hop2]
941 else:
942 next_hop_6 = NEXT_HOP_6
943
944 result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_6)
945 assert result is True, "Testcase {} : Failed \n Error {}".format(
946 tc_name, result
947 )
948
949 logger.info("[Step 3] : Kill BGPd daemon on R1 and R4..")
950
951 # Kill BGPd daemon on R1
952 kill_router_daemons(tgen, "r1", ["bgpd"])
953
954 # Kill BGPd daemon on R4
955 kill_router_daemons(tgen, "r4", ["bgpd"])
956
957 for addr_type in ADDR_TYPES:
958 # Verifying RIB routes
959 next_hop_6 = ["fd00:0:0:1::1"]
960 if addr_type == "ipv4":
961 next_hop_4 = NEXT_HOP_4[0]
962
963 result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_4)
964 assert result is True, "Testcase {} : Failed \n Error {}".format(
965 tc_name, result
966 )
967
968 if addr_type == "ipv6":
969 if "link_local" in PREFERRED_NEXT_HOP:
970 next_hop_6 = get_frr_ipv6_linklocal(tgen, peer1, intf=intf1)
971 else:
972 next_hop_6 = NEXT_HOP_6[0]
973
974 result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_6)
975
976 # Verifying RIB routes
977 if addr_type == "ipv4":
978 next_hop_4 = NEXT_HOP_4[1]
979 result = verify_rib(
980 tgen, addr_type, dut, input_dict_2, next_hop_4, expected=False
981 )
982 assert result is not True, (
983 "Testcase {} : Failed \n "
984 "r3: routes are still present in BGP RIB\n Error: {}".format(
985 tc_name, result
986 )
987 )
988 logger.info(" Expected behavior: {}".format(result))
989
990 if addr_type == "ipv6":
991 if "link_local" in PREFERRED_NEXT_HOP:
992 next_hop_6 = get_frr_ipv6_linklocal(tgen, peer2, intf=intf2)
993 else:
994 next_hop_6 = NEXT_HOP_6[1]
995
996 result = verify_rib(
997 tgen, addr_type, dut, input_dict_2, next_hop_6, expected=False
998 )
999 assert result is not True, (
1000 "Testcase {} : Failed \n "
1001 "r3: routes are still present in ZEBRA\n Error: {}".format(
1002 tc_name, result
1003 )
1004 )
1005 logger.info(" Expected behavior: {}".format(result))
1006
1007 logger.info("[Step 4] : Start BGPd daemon on R1 and R4..")
1008
1009 # Start BGPd daemon on R1
1010 start_router_daemons(tgen, "r1", ["bgpd"])
1011
1012 # Start BGPd daemon on R4
1013 start_router_daemons(tgen, "r4", ["bgpd"])
1014
1015 write_test_footer(tc_name)
1016
1017
1018 def test_BGP_GR_chaos_34_2_p1(request):
1019 """
1020 Test Objective : Restarting node doesn't preserve the forwarding
1021 state verify the behaviour on helper node, if it still keeps the
1022 stale routes.
1023 """
1024
1025 tgen = get_topogen()
1026 tc_name = request.node.name
1027 write_test_header(tc_name)
1028
1029 # Check router status
1030 check_router_status(tgen)
1031
1032 # Don't run this test if we have any failure.
1033 if tgen.routers_have_failure():
1034 pytest.skip(tgen.errors)
1035
1036 # Creating configuration from JSON
1037 reset_config_on_routers(tgen)
1038
1039 logger.info(
1040 " Test Case : test_BGP_GR_chaos_34 "
1041 "BGP GR "
1042 "[Restart Mode]R1---R3[Helper Mode]"
1043 )
1044
1045 logger.info("[Step 1] : Configure restarting" " router R1 to prevent ")
1046 logger.info("[Step 2] : Reset the session" " between R1 and R3..")
1047
1048 # Configure graceful-restart
1049 input_dict = {
1050 "r1": {
1051 "bgp": {
1052 "graceful-restart": {"preserve-fw-state": True, "disable-eor": True},
1053 "address_family": {
1054 "ipv4": {
1055 "unicast": {
1056 "neighbor": {
1057 "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
1058 }
1059 }
1060 },
1061 "ipv6": {
1062 "unicast": {
1063 "neighbor": {
1064 "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
1065 }
1066 }
1067 },
1068 },
1069 }
1070 },
1071 "r3": {
1072 "bgp": {
1073 "address_family": {
1074 "ipv4": {
1075 "unicast": {
1076 "neighbor": {
1077 "r1": {
1078 "dest_link": {
1079 "r3": {"graceful-restart-helper": True}
1080 }
1081 }
1082 }
1083 }
1084 },
1085 "ipv6": {
1086 "unicast": {
1087 "neighbor": {
1088 "r1": {
1089 "dest_link": {
1090 "r3": {"graceful-restart-helper": True}
1091 }
1092 }
1093 }
1094 }
1095 },
1096 }
1097 }
1098 },
1099 }
1100
1101 configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
1102
1103 for addr_type in ADDR_TYPES:
1104 result = verify_graceful_restart(
1105 tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
1106 )
1107 assert result is True, "Testcase {} : Failed \n Error {}".format(
1108 tc_name, result
1109 )
1110
1111 # Verify f-bit before killing BGPd daemon
1112 result = verify_f_bit(tgen, topo, addr_type, input_dict, "r3", "r1")
1113 assert result is True, "Testcase {} : Failed \n Error {}".format(
1114 tc_name, result
1115 )
1116
1117 # Verifying BGP RIB routes after starting BGPd daemon
1118 dut = "r3"
1119 input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
1120 result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
1121 assert result is True, "Testcase {} : Failed \n Error {}".format(
1122 tc_name, result
1123 )
1124
1125 # Verifying RIB routes
1126 result = verify_rib(tgen, addr_type, dut, input_dict_1)
1127 assert result is True, "Testcase {} : Failed \n Error {}".format(
1128 tc_name, result
1129 )
1130
1131 logger.info("[Step 3] : Kill BGPd daemon on R1..")
1132
1133 # Kill BGPd daemon on R1
1134 kill_router_daemons(tgen, "r1", ["bgpd"])
1135
1136 logger.info("[Step 4] : Withdraw/delete the prefixes " "originated from R1..")
1137
1138 # Api call to delete advertised networks
1139 network = {"ipv4": "101.0.20.1/32", "ipv6": "1::1/128"}
1140 for addr_type in ADDR_TYPES:
1141 input_dict_2 = {
1142 "r1": {
1143 "bgp": {
1144 "address_family": {
1145 addr_type: {
1146 "unicast": {
1147 "advertise_networks": [
1148 {
1149 "network": network[addr_type],
1150 "no_of_network": 5,
1151 "delete": True,
1152 }
1153 ]
1154 }
1155 }
1156 }
1157 }
1158 }
1159 }
1160
1161 result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2)
1162 assert result is True, "Testcase {} : Failed \n Error {}".format(
1163 tc_name, result
1164 )
1165
1166 logger.info("[Step 5] : Remove the CLI from R1's config to " "set the F-bit..")
1167
1168 # Modify graceful-restart config not to set f-bit
1169 # and write to /etc/frr
1170 input_dict_2 = {"r1": {"bgp": {"graceful-restart": {"preserve-fw-state": False}}}}
1171
1172 result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2)
1173 assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result)
1174
1175 logger.info("[Step 6] : Bring up the BGPd daemon on R1 again..")
1176
1177 # Start BGPd daemon on R1
1178 start_router_daemons(tgen, "r1", ["bgpd"])
1179
1180 for addr_type in ADDR_TYPES:
1181 # Verify f-bit after starting BGPd daemon
1182 result = verify_f_bit(
1183 tgen, topo, addr_type, input_dict, "r3", "r1", expected=False
1184 )
1185 assert (
1186 result is not True
1187 ), "Testcase {} : Failed \n " "r3: F-bit is set to True\n Error: {}".format(
1188 tc_name, result
1189 )
1190 logger.info(" Expected behavior: {}".format(result))
1191
1192 # Verifying BGP RIB routes after starting BGPd daemon
1193 input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
1194 result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
1195 assert result is not True, (
1196 "Testcase {} : Failed \n "
1197 "r3: routes are still present in BGP RIB\n Error: {}".format(
1198 tc_name, result
1199 )
1200 )
1201 logger.info(" Expected behavior: {}".format(result))
1202
1203 # Verifying RIB routes
1204 result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
1205 assert result is not True, (
1206 "Testcase {} : Failed \n "
1207 "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
1208 )
1209 logger.info(" Expected behavior: {}".format(result))
1210
1211 write_test_footer(tc_name)
1212
1213
1214 if __name__ == "__main__":
1215 args = ["-s"] + sys.argv[1:]
1216 sys.exit(pytest.main(args))