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 eBGP peers
27 2. Verify graceful-shutdown functionality when daemons
28 bgpd/zebra/staticd and frr services are restarted with eBGP peers
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 sys
.path
.append(os
.path
.join(CWD
, "../../"))
41 # pylint: disable=C0413
42 # Import topogen and topotest helpers
43 from lib
.topogen
import Topogen
, get_topogen
45 from lib
.common_config
import (
51 reset_config_on_routers
,
53 get_frr_ipv6_linklocal
,
59 create_bgp_community_lists
,
60 required_linux_kernel_version
,
62 from lib
.topolog
import logger
64 verify_bgp_convergence
,
67 verify_bgp_attributes
,
69 from lib
.topojson
import build_config_from_json
72 pytestmark
= [pytest
.mark
.bgpd
, pytest
.mark
.staticd
]
76 NETWORK
= {"ipv4": "100.0.10.1/32", "ipv6": "1::1/128"}
77 NEXT_HOP_IP_1
= {"ipv4": "10.0.2.1", "ipv6": "fd00:0:0:1::1"}
78 NEXT_HOP_IP_2
= {"ipv4": "10.0.4.2", "ipv6": "fd00:0:0:3::2"}
79 PREFERRED_NEXT_HOP
= "link_local"
80 BGP_CONVERGENCE
= False
83 def setup_module(mod
):
85 Sets up the pytest environment
92 # Required linux kernel version for this suite to run.
93 result
= required_linux_kernel_version("4.16")
94 if result
is not True:
95 pytest
.skip("Kernel requirements are not met")
97 testsuite_run_time
= time
.asctime(time
.localtime(time
.time()))
98 logger
.info("Testsuite start time: {}".format(testsuite_run_time
))
101 logger
.info("Running setup_module to create topology")
103 # This function initiates the topology build with Topogen...
104 json_file
= "{}/ebgp_gshut_topo1.json".format(CWD
)
105 tgen
= Topogen(json_file
, mod
.__name
__)
107 topo
= tgen
.json_topo
108 # ... and here it calls Mininet initialization functions.
110 # Starting topology, create tmp files which are loaded to routers
111 # to start deamons and then start routers
114 # Creating configuration from JSON
115 build_config_from_json(tgen
, topo
)
117 # Don't run this test if we have any failure.
118 if tgen
.routers_have_failure():
119 pytest
.skip(tgen
.errors
)
121 # Api call verify whether BGP is converged
122 ADDR_TYPES
= check_address_types()
124 BGP_CONVERGENCE
= verify_bgp_convergence(tgen
, topo
)
125 assert BGP_CONVERGENCE
is True, "setup_module :Failed \n Error:" " {}".format(
129 logger
.info("Running setup_module() done")
132 def teardown_module():
134 Teardown the pytest environment.
139 logger
.info("Running teardown_module to delete topology")
143 # Stop toplogy and Remove tmp files
147 ###########################
149 ###########################
152 def next_hop_per_address_family(
153 tgen
, dut
, peer
, addr_type
, next_hop_dict
, preferred_next_hop
=PREFERRED_NEXT_HOP
156 This function returns link_local or global next_hop per address-family
159 intferface
= topo
["routers"][peer
]["links"]["{}".format(dut
)]["interface"]
160 if addr_type
== "ipv6" and "link_local" in preferred_next_hop
:
161 next_hop
= get_frr_ipv6_linklocal(tgen
, peer
, intf
=intferface
)
163 next_hop
= next_hop_dict
[addr_type
]
168 ###########################
170 ###########################
173 def test_verify_graceful_shutdown_functionality_with_eBGP_peers_p0(request
):
175 Verify graceful-shutdown functionality with eBGP peers
178 tc_name
= request
.node
.name
179 write_test_header(tc_name
)
181 reset_config_on_routers(tgen
)
183 step("Done in base config: Configure base config as per the topology")
184 step("Base config should be up, verify using BGP convergence")
185 result
= verify_bgp_convergence(tgen
, topo
)
186 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
188 step("Done in base config: Advertise prefixes from R1")
189 step("Verify BGP routes are received at R3 with best path from R3 to R1")
191 for addr_type
in ADDR_TYPES
:
193 next_hop1
= next_hop_per_address_family(
194 tgen
, "r3", "r1", addr_type
, NEXT_HOP_IP_1
196 next_hop2
= next_hop_per_address_family(
197 tgen
, "r3", "r4", addr_type
, NEXT_HOP_IP_2
200 input_topo
= {key
: topo
["routers"][key
] for key
in ["r1"]}
201 result
= verify_bgp_rib(
202 tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
, next_hop2
]
204 assert result
is True, "Test case {} : Failed \n Error: {}".format(
208 result
= verify_rib(tgen
, addr_type
, dut
, input_topo
, next_hop
=next_hop1
)
209 assert result
is True, "Test case {} : Failed \n Error: {}".format(
213 step("On R1 configure:")
214 step("Create standard bgp community-list to permit graceful-shutdown:")
217 "bgp_community_lists": [
219 "community_type": "standard",
222 "value": "graceful-shutdown",
228 result
= create_bgp_community_lists(tgen
, input_dict_1
)
229 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
231 step("Create route-map to set community GSHUT in OUT direction")
240 "set": {"community": {"num": "graceful-shutdown"}},
247 result
= create_route_maps(tgen
, input_dict_2
)
248 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
295 result
= create_router_bgp(tgen
, topo
, input_dict_3
)
296 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
299 "FRR is setting local-pref to 0 by-default on receiver GSHUT community, "
300 "below step is not needed, but keeping for reference"
303 "On R3, apply route-map IN direction to match GSHUT community "
304 "and set local-preference to 0."
308 "Verify BGP convergence on R3 and ensure all the neighbours state "
312 result
= verify_bgp_convergence(tgen
, topo
)
313 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
315 step("Verify BGP routes on R3:")
316 step("local pref for routes coming from R1 is set to 0.")
318 for addr_type
in ADDR_TYPES
:
319 rmap_dict
= {"r1": {"route_maps": {"GSHUT-OUT": [{"set": {"locPrf": 0}}],}}}
321 static_routes
= [NETWORK
[addr_type
]]
322 result
= verify_bgp_attributes(
323 tgen
, addr_type
, dut
, static_routes
, "GSHUT-OUT", rmap_dict
325 assert result
is True, "Test case {} : Failed \n Error: {}".format(
329 step("Ensure that best path is selected from R4 to R3.")
331 for addr_type
in ADDR_TYPES
:
333 next_hop1
= next_hop_per_address_family(
334 tgen
, "r3", "r1", addr_type
, NEXT_HOP_IP_1
336 next_hop2
= next_hop_per_address_family(
337 tgen
, "r3", "r4", addr_type
, NEXT_HOP_IP_2
340 input_topo
= {key
: topo
["routers"][key
] for key
in ["r1"]}
341 result
= verify_bgp_rib(
342 tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
, next_hop2
]
344 assert result
is True, "Test case {} : Failed \n Error: {}".format(
348 result
= verify_rib(tgen
, addr_type
, dut
, input_topo
, next_hop
=next_hop2
)
349 assert result
is True, "Test case {} : Failed \n Error: {}".format(
353 write_test_footer(tc_name
)
356 def test_verify_restarting_zebra_bgpd_staticd_frr_with_eBGP_peers_p0(request
):
358 Verify graceful-shutdown functionality when daemons bgpd/zebra/staticd and
359 frr services are restarted with eBGP peers
362 tc_name
= request
.node
.name
363 write_test_header(tc_name
)
365 reset_config_on_routers(tgen
)
367 step("Done in base config: Configure base config as per the topology")
368 step("Base config should be up, verify using BGP convergence")
369 result
= verify_bgp_convergence(tgen
, topo
)
370 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
372 step("Done in base config: Advertise prefixes from R1")
373 step("Verify BGP routes are received at R3 with best path from R3 to R1")
375 for addr_type
in ADDR_TYPES
:
377 next_hop1
= next_hop_per_address_family(
378 tgen
, "r3", "r1", addr_type
, NEXT_HOP_IP_1
380 next_hop2
= next_hop_per_address_family(
381 tgen
, "r3", "r4", addr_type
, NEXT_HOP_IP_2
384 input_topo
= {key
: topo
["routers"][key
] for key
in ["r1"]}
385 result
= verify_bgp_rib(
386 tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
, next_hop2
]
388 assert result
is True, "Test case {} : Failed \n Error: {}".format(
392 result
= verify_rib(tgen
, addr_type
, dut
, input_topo
, next_hop
=next_hop1
)
393 assert result
is True, "Test case {} : Failed \n Error: {}".format(
397 step("On R1 configure:")
398 step("Create standard bgp community-list to permit graceful-shutdown:")
401 "bgp_community_lists": [
403 "community_type": "standard",
406 "value": "graceful-shutdown",
412 result
= create_bgp_community_lists(tgen
, input_dict_1
)
413 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
415 step("Create route-map to set community GSHUT in OUT direction")
424 "set": {"community": {"num": "graceful-shutdown"}},
431 result
= create_route_maps(tgen
, input_dict_2
)
432 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
479 result
= create_router_bgp(tgen
, topo
, input_dict_3
)
480 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
483 "FRR is setting local-pref to 0 by-default on receiver GSHUT community, "
484 "below step is not needed, but keeping for reference"
487 "On R3, apply route-map IN direction to match GSHUT community "
488 "and set local-preference to 0."
492 "Verify BGP convergence on R3 and ensure all the neighbours state "
496 result
= verify_bgp_convergence(tgen
, topo
)
497 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
499 step("Verify BGP routes on R3:")
500 step("local pref for routes coming from R1 is set to 0.")
502 for addr_type
in ADDR_TYPES
:
503 rmap_dict
= {"r1": {"route_maps": {"GSHUT-OUT": [{"set": {"locPrf": 0}}]}}}
505 static_routes
= [NETWORK
[addr_type
]]
506 result
= verify_bgp_attributes(
507 tgen
, addr_type
, dut
, static_routes
, "GSHUT-OUT", rmap_dict
509 assert result
is True, "Test case {} : Failed \n Error: {}".format(
513 step("Ensure that best path is selected from R4 to R3.")
515 for addr_type
in ADDR_TYPES
:
517 next_hop1
= next_hop_per_address_family(
518 tgen
, "r3", "r1", addr_type
, NEXT_HOP_IP_1
520 next_hop2
= next_hop_per_address_family(
521 tgen
, "r3", "r4", addr_type
, NEXT_HOP_IP_2
524 input_topo
= {key
: topo
["routers"][key
] for key
in ["r1"]}
525 result
= verify_bgp_rib(
526 tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
, next_hop2
]
528 assert result
is True, "Test case {} : Failed \n Error: {}".format(
532 result
= verify_rib(tgen
, addr_type
, dut
, input_topo
, next_hop
=next_hop2
)
533 assert result
is True, "Test case {} : Failed \n Error: {}".format(
537 step("Restart daemons and frr services")
539 for daemon
in ["bgpd", "zebra", "staticd", "frr"]:
541 kill_router_daemons(tgen
, "r3", ["staticd"])
542 start_router_daemons(tgen
, "r3", ["staticd"])
544 stop_router(tgen
, "r3")
545 start_router(tgen
, "r3")
548 "Verify BGP convergence on R3 and ensure all the neighbours state "
552 result
= verify_bgp_convergence(tgen
, topo
)
553 assert result
is True, "Test case {} : Failed \n Error: {}".format(
557 step("Verify BGP routes on R3:")
558 step("local pref for routes coming from R1 is set to 0.")
560 for addr_type
in ADDR_TYPES
:
561 rmap_dict
= {"r1": {"route_maps": {"GSHUT-OUT": [{"set": {"locPrf": 0}}]}}}
563 static_routes
= [NETWORK
[addr_type
]]
564 result
= verify_bgp_attributes(
565 tgen
, addr_type
, dut
, static_routes
, "GSHUT-OUT", rmap_dict
567 assert result
is True, "Test case {} : Failed \n Error: {}".format(
571 step("Ensure that best path is selected from R4 to R3.")
573 for addr_type
in ADDR_TYPES
:
575 next_hop1
= next_hop_per_address_family(
576 tgen
, "r3", "r1", addr_type
, NEXT_HOP_IP_1
578 next_hop2
= next_hop_per_address_family(
579 tgen
, "r3", "r4", addr_type
, NEXT_HOP_IP_2
582 input_topo
= {key
: topo
["routers"][key
] for key
in ["r1"]}
583 result
= verify_bgp_rib(
584 tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
, next_hop2
]
586 assert result
is True, "Test case {} : Failed \n Error: {}".format(
590 result
= verify_rib(tgen
, addr_type
, dut
, input_topo
, next_hop
=next_hop2
)
591 assert result
is True, "Test case {} : Failed \n Error: {}".format(
595 write_test_footer(tc_name
)
598 if __name__
== "__main__":
599 args
= ["-s"] + sys
.argv
[1:]
600 sys
.exit(pytest
.main(args
))