4 # Copyright (c) 2021 by VMware, Inc. ("VMware")
5 # Used Copyright (c) 2018 by Network Device Education Foundation, Inc.
6 # ("NetDEF") in this file.
8 # Permission to use, copy, modify, and/or distribute this software
9 # for any purpose with or without fee is hereby granted, provided
10 # that the above copyright notice and this permission notice appear
13 # THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
14 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
16 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
17 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
19 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
25 Following tests are covered to test ecmp functionality on BGP GSHUT.
26 1. Verify graceful-shutdown functionality with iBGP peers
27 2. Verify graceful-shutdown functionality after
28 deleting/re-adding route-map with iBGP peers
37 # Save the Current Working Directory to find configuration files.
38 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
39 sys
.path
.append(os
.path
.join(CWD
, "../"))
40 sys
.path
.append(os
.path
.join(CWD
, "../../"))
42 # pylint: disable=C0413
43 # Import topogen and topotest helpers
44 from lib
.topogen
import Topogen
, get_topogen
45 from lib
.micronet_compat
import Topo
46 from time
import sleep
48 from lib
.common_config
import (
56 reset_config_on_routers
,
58 get_frr_ipv6_linklocal
,
64 create_bgp_community_lists
,
66 required_linux_kernel_version
,
68 from lib
.topolog
import logger
70 verify_bgp_convergence
,
74 verify_bgp_attributes
,
76 from lib
.topojson
import build_topo_from_json
, build_config_from_json
78 pytestmark
= [pytest
.mark
.bgpd
, pytest
.mark
.staticd
]
82 NETWORK
= {"ipv4": "100.0.10.1/32", "ipv6": "1::1/128"}
83 NEXT_HOP_IP_1
= {"ipv4": "10.0.3.1", "ipv6": "fd00:0:0:3::1"}
84 NEXT_HOP_IP_2
= {"ipv4": "10.0.4.1", "ipv6": "fd00:0:0:2::1"}
85 PREFERRED_NEXT_HOP
= "link_local"
86 BGP_CONVERGENCE
= False
89 def setup_module(mod
):
91 Sets up the pytest environment
98 # Required linux kernel version for this suite to run.
99 result
= required_linux_kernel_version("4.16")
100 if result
is not True:
101 pytest
.skip("Kernel requirements are not met")
103 testsuite_run_time
= time
.asctime(time
.localtime(time
.time()))
104 logger
.info("Testsuite start time: {}".format(testsuite_run_time
))
105 logger
.info("=" * 40)
107 logger
.info("Running setup_module to create topology")
109 # This function initiates the topology build with Topogen...
110 json_file
= "{}/ibgp_gshut_topo1.json".format(CWD
)
111 tgen
= Topogen(json_file
, mod
.__name
__)
113 topo
= tgen
.json_topo
114 # ... and here it calls Mininet initialization functions.
116 # Starting topology, create tmp files which are loaded to routers
117 # to start deamons and then start routers
120 # Creating configuration from JSON
121 build_config_from_json(tgen
, topo
)
123 # Don't run this test if we have any failure.
124 if tgen
.routers_have_failure():
125 pytest
.skip(tgen
.errors
)
127 # Api call verify whether BGP is converged
128 ADDR_TYPES
= check_address_types()
130 BGP_CONVERGENCE
= verify_bgp_convergence(tgen
, topo
)
131 assert BGP_CONVERGENCE
is True, "setup_module :Failed \n Error:" " {}".format(
135 logger
.info("Running setup_module() done")
138 def teardown_module():
140 Teardown the pytest environment.
145 logger
.info("Running teardown_module to delete topology")
149 # Stop toplogy and Remove tmp files
153 ###########################
155 ###########################
158 def next_hop_per_address_family(
159 tgen
, dut
, peer
, addr_type
, next_hop_dict
, preferred_next_hop
=PREFERRED_NEXT_HOP
162 This function returns link_local or global next_hop per address-family
165 intferface
= topo
["routers"][peer
]["links"]["{}".format(dut
)]["interface"]
166 if addr_type
== "ipv6" and "link_local" in preferred_next_hop
:
167 next_hop
= get_frr_ipv6_linklocal(tgen
, peer
, intf
=intferface
)
169 next_hop
= next_hop_dict
[addr_type
]
174 ###########################
176 ###########################
179 def test_verify_graceful_shutdown_functionality_with_iBGP_peers_p0(request
):
181 Verify graceful-shutdown functionality with iBGP peers
184 tc_name
= request
.node
.name
185 write_test_header(tc_name
)
187 reset_config_on_routers(tgen
)
189 step("Done in base config: Configure base config as per the topology")
190 step("Base config should be up, verify using BGP convergence")
191 result
= verify_bgp_convergence(tgen
, topo
)
192 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
194 step("Done in base config: Advertise prefixes from R1")
195 step("Verify BGP routes are received at R4 with best path from R3 to R1")
197 for addr_type
in ADDR_TYPES
:
199 next_hop1
= next_hop_per_address_family(
200 tgen
, "r4", "r2", addr_type
, NEXT_HOP_IP_1
202 next_hop2
= next_hop_per_address_family(
203 tgen
, "r4", "r3", addr_type
, NEXT_HOP_IP_2
206 input_topo
= {key
: topo
["routers"][key
] for key
in ["r1"]}
207 result
= verify_bgp_rib(
208 tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
, next_hop2
]
210 assert result
is True, "Test case {} : Failed \n Error: {}".format(
215 tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
, next_hop2
]
217 assert result
is True, "Test case {} : Failed \n Error: {}".format(
221 step("On R1 configure:")
222 step("Create standard bgp community-list to permit graceful-shutdown:")
225 "bgp_community_lists": [
227 "community_type": "standard",
230 "value": "graceful-shutdown",
236 result
= create_bgp_community_lists(tgen
, input_dict_1
)
237 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
239 step("Create route-map to set community GSHUT in OUT direction")
248 "set": {"community": {"num": "graceful-shutdown"}},
255 result
= create_route_maps(tgen
, input_dict_2
)
256 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
303 result
= create_router_bgp(tgen
, topo
, input_dict_3
)
304 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
307 "FRR is setting local-pref to 0 by-default on receiver GSHUT community, "
308 "below step is not needed, but keeping for reference"
311 "On R3, apply route-map IN direction to match GSHUT community "
312 "and set local-preference to 0."
316 "Verify BGP convergence on R4 and ensure all the neighbours state "
320 result
= verify_bgp_convergence(tgen
, topo
)
321 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
323 step("Verify BGP routes on R4:")
324 step("local pref for routes coming from R1 is set to 0.")
326 for addr_type
in ADDR_TYPES
:
327 rmap_dict
= {"r1": {"route_maps": {"GSHUT-OUT": [{"set": {"locPrf": 0}}],}}}
329 static_routes
= [NETWORK
[addr_type
]]
330 result
= verify_bgp_attributes(
331 tgen
, addr_type
, dut
, static_routes
, "GSHUT-OUT", rmap_dict
333 assert result
is True, "Test case {} : Failed \n Error: {}".format(
337 step("Ensure that best path is selected from R4 to R3.")
339 for addr_type
in ADDR_TYPES
:
341 next_hop1
= next_hop_per_address_family(
342 tgen
, "r4", "r2", addr_type
, NEXT_HOP_IP_1
344 next_hop2
= next_hop_per_address_family(
345 tgen
, "r4", "r3", addr_type
, NEXT_HOP_IP_2
348 input_topo
= {key
: topo
["routers"][key
] for key
in ["r1"]}
349 result
= verify_bgp_rib(
350 tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
, next_hop2
]
352 assert result
is True, "Test case {} : Failed \n Error: {}".format(
356 result
= verify_rib(tgen
, addr_type
, dut
, input_topo
, next_hop
=next_hop1
)
357 assert result
is True, "Test case {} : Failed \n Error: {}".format(
361 write_test_footer(tc_name
)
364 def test_verify_deleting_re_adding_route_map_with_iBGP_peers_p0(request
):
366 Verify graceful-shutdown functionality after deleting/re-adding route-map
370 tc_name
= request
.node
.name
371 write_test_header(tc_name
)
373 reset_config_on_routers(tgen
)
375 step("Done in base config: Configure base config as per the topology")
376 step("Base config should be up, verify using BGP convergence")
377 result
= verify_bgp_convergence(tgen
, topo
)
378 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
380 step("Done in base config: Advertise prefixes from R1")
381 step("Verify BGP routes are received at R4 with best path from R3 to R1")
383 for addr_type
in ADDR_TYPES
:
385 next_hop1
= next_hop_per_address_family(
386 tgen
, "r4", "r2", addr_type
, NEXT_HOP_IP_1
388 next_hop2
= next_hop_per_address_family(
389 tgen
, "r4", "r3", addr_type
, NEXT_HOP_IP_2
392 input_topo
= {key
: topo
["routers"][key
] for key
in ["r1"]}
393 result
= verify_bgp_rib(
394 tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
, next_hop2
]
396 assert result
is True, "Test case {} : Failed \n Error: {}".format(
401 tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
, next_hop2
]
403 assert result
is True, "Test case {} : Failed \n Error: {}".format(
407 step("On R1 configure:")
408 step("Create standard bgp community-list to permit graceful-shutdown:")
411 "bgp_community_lists": [
413 "community_type": "standard",
416 "value": "graceful-shutdown",
422 result
= create_bgp_community_lists(tgen
, input_dict_1
)
423 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
425 step("Create route-map to set community GSHUT in OUT direction")
434 "set": {"community": {"num": "graceful-shutdown"}},
441 result
= create_route_maps(tgen
, input_dict_2
)
442 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
489 result
= create_router_bgp(tgen
, topo
, input_dict_3
)
490 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
493 "FRR is setting local-pref to 0 by-default on receiver GSHUT community, "
494 "below step is not needed, but keeping for reference"
497 "On R3, apply route-map IN direction to match GSHUT community "
498 "and set local-preference to 0."
502 "Verify BGP convergence on R4 and ensure all the neighbours state "
506 result
= verify_bgp_convergence(tgen
, topo
)
507 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
509 step("Verify BGP routes on R4:")
510 step("local pref for routes coming from R1 is set to 0.")
512 for addr_type
in ADDR_TYPES
:
513 rmap_dict
= {"r1": {"route_maps": {"GSHUT-OUT": [{"set": {"locPrf": 0}}],}}}
515 static_routes
= [NETWORK
[addr_type
]]
516 result
= verify_bgp_attributes(
517 tgen
, addr_type
, dut
, static_routes
, "GSHUT-OUT", rmap_dict
519 assert result
is True, "Test case {} : Failed \n Error: {}".format(
523 step("Ensure that best path is selected from R4 to R3.")
525 for addr_type
in ADDR_TYPES
:
527 next_hop1
= next_hop_per_address_family(
528 tgen
, "r4", "r2", addr_type
, NEXT_HOP_IP_1
530 next_hop2
= next_hop_per_address_family(
531 tgen
, "r4", "r3", addr_type
, NEXT_HOP_IP_2
534 input_topo
= {key
: topo
["routers"][key
] for key
in ["r1"]}
535 result
= verify_bgp_rib(
536 tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
, next_hop2
]
538 assert result
is True, "Test case {} : Failed \n Error: {}".format(
542 result
= verify_rib(tgen
, addr_type
, dut
, input_topo
, next_hop
=next_hop1
)
543 assert result
is True, "Test case {} : Failed \n Error: {}".format(
547 step("Delete route-map from R1")
556 "community": {"num": "graceful-shutdown", "delete": True}
564 result
= create_route_maps(tgen
, del_rmap_dict
)
565 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
568 "Verify BGP convergence on R3 and ensure that all neighbor state "
571 result
= verify_bgp_convergence(tgen
, topo
)
572 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
574 step("Verify BGP routes on R4:")
575 step("Ensure that best path is selected from R1->R3")
577 for addr_type
in ADDR_TYPES
:
579 next_hop1
= next_hop_per_address_family(
580 tgen
, "r4", "r2", addr_type
, NEXT_HOP_IP_1
582 next_hop2
= next_hop_per_address_family(
583 tgen
, "r4", "r3", addr_type
, NEXT_HOP_IP_2
586 input_topo
= {key
: topo
["routers"][key
] for key
in ["r1"]}
587 result
= verify_bgp_rib(tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
])
588 assert result
is True, "Test case {} : Failed \n Error: {}".format(
592 result
= verify_rib(tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
])
593 assert result
is True, "Test case {} : Failed \n Error: {}".format(
597 step("Re-add route-map in R1")
598 result
= create_route_maps(tgen
, input_dict_2
)
599 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
602 "Verify BGP convergence on R3 and ensure all the neighbours state "
606 result
= verify_bgp_convergence(tgen
, topo
)
607 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
609 step("Verify BGP routes on R4:")
610 step("local pref for routes coming from R1 is set to 0.")
612 for addr_type
in ADDR_TYPES
:
613 rmap_dict
= {"r1": {"route_maps": {"GSHUT-OUT": [{"set": {"locPrf": 0}}]}}}
615 static_routes
= [NETWORK
[addr_type
]]
616 result
= verify_bgp_attributes(
617 tgen
, addr_type
, dut
, static_routes
, "GSHUT-OUT", rmap_dict
619 assert result
is True, "Test case {} : Failed \n Error: {}".format(
623 step("Ensure that best path is selected from R4 to R3.")
625 for addr_type
in ADDR_TYPES
:
627 next_hop1
= next_hop_per_address_family(
628 tgen
, "r4", "r2", addr_type
, NEXT_HOP_IP_1
630 next_hop2
= next_hop_per_address_family(
631 tgen
, "r4", "r3", addr_type
, NEXT_HOP_IP_2
634 input_topo
= {key
: topo
["routers"][key
] for key
in ["r1"]}
635 result
= verify_bgp_rib(
636 tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
, next_hop2
]
638 assert result
is True, "Test case {} : Failed \n Error: {}".format(
642 result
= verify_rib(tgen
, addr_type
, dut
, input_topo
, next_hop
=next_hop1
)
643 assert result
is True, "Test case {} : Failed \n Error: {}".format(
647 write_test_footer(tc_name
)
650 if __name__
== "__main__":
651 args
= ["-s"] + sys
.argv
[1:]
652 sys
.exit(pytest
.main(args
))