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, kernel version should be >=4.16")
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 daemons 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
:
322 "GSHUT-OUT": [{"set": {"locPrf": 0}}],
327 static_routes
= [NETWORK
[addr_type
]]
328 result
= verify_bgp_attributes(
329 tgen
, addr_type
, dut
, static_routes
, "GSHUT-OUT", rmap_dict
331 assert result
is True, "Test case {} : Failed \n Error: {}".format(
335 step("Ensure that best path is selected from R4 to R3.")
337 for addr_type
in ADDR_TYPES
:
339 next_hop1
= next_hop_per_address_family(
340 tgen
, "r3", "r1", addr_type
, NEXT_HOP_IP_1
342 next_hop2
= next_hop_per_address_family(
343 tgen
, "r3", "r4", addr_type
, NEXT_HOP_IP_2
346 input_topo
= {key
: topo
["routers"][key
] for key
in ["r1"]}
347 result
= verify_bgp_rib(
348 tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
, next_hop2
]
350 assert result
is True, "Test case {} : Failed \n Error: {}".format(
354 result
= verify_rib(tgen
, addr_type
, dut
, input_topo
, next_hop
=next_hop2
)
355 assert result
is True, "Test case {} : Failed \n Error: {}".format(
359 write_test_footer(tc_name
)
362 def test_verify_restarting_zebra_bgpd_staticd_frr_with_eBGP_peers_p0(request
):
364 Verify graceful-shutdown functionality when daemons bgpd/zebra/staticd and
365 frr services are restarted with eBGP peers
368 tc_name
= request
.node
.name
369 write_test_header(tc_name
)
371 reset_config_on_routers(tgen
)
373 step("Done in base config: Configure base config as per the topology")
374 step("Base config should be up, verify using BGP convergence")
375 result
= verify_bgp_convergence(tgen
, topo
)
376 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
378 step("Done in base config: Advertise prefixes from R1")
379 step("Verify BGP routes are received at R3 with best path from R3 to R1")
381 for addr_type
in ADDR_TYPES
:
383 next_hop1
= next_hop_per_address_family(
384 tgen
, "r3", "r1", addr_type
, NEXT_HOP_IP_1
386 next_hop2
= next_hop_per_address_family(
387 tgen
, "r3", "r4", addr_type
, NEXT_HOP_IP_2
390 input_topo
= {key
: topo
["routers"][key
] for key
in ["r1"]}
391 result
= verify_bgp_rib(
392 tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
, next_hop2
]
394 assert result
is True, "Test case {} : Failed \n Error: {}".format(
398 result
= verify_rib(tgen
, addr_type
, dut
, input_topo
, next_hop
=next_hop1
)
399 assert result
is True, "Test case {} : Failed \n Error: {}".format(
403 step("On R1 configure:")
404 step("Create standard bgp community-list to permit graceful-shutdown:")
407 "bgp_community_lists": [
409 "community_type": "standard",
412 "value": "graceful-shutdown",
418 result
= create_bgp_community_lists(tgen
, input_dict_1
)
419 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
421 step("Create route-map to set community GSHUT in OUT direction")
430 "set": {"community": {"num": "graceful-shutdown"}},
437 result
= create_route_maps(tgen
, input_dict_2
)
438 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
485 result
= create_router_bgp(tgen
, topo
, input_dict_3
)
486 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
489 "FRR is setting local-pref to 0 by-default on receiver GSHUT community, "
490 "below step is not needed, but keeping for reference"
493 "On R3, apply route-map IN direction to match GSHUT community "
494 "and set local-preference to 0."
498 "Verify BGP convergence on R3 and ensure all the neighbours state "
502 result
= verify_bgp_convergence(tgen
, topo
)
503 assert result
is True, "Test case {} : Failed \n Error: {}".format(tc_name
, result
)
505 step("Verify BGP routes on R3:")
506 step("local pref for routes coming from R1 is set to 0.")
508 for addr_type
in ADDR_TYPES
:
509 rmap_dict
= {"r1": {"route_maps": {"GSHUT-OUT": [{"set": {"locPrf": 0}}]}}}
511 static_routes
= [NETWORK
[addr_type
]]
512 result
= verify_bgp_attributes(
513 tgen
, addr_type
, dut
, static_routes
, "GSHUT-OUT", rmap_dict
515 assert result
is True, "Test case {} : Failed \n Error: {}".format(
519 step("Ensure that best path is selected from R4 to R3.")
521 for addr_type
in ADDR_TYPES
:
523 next_hop1
= next_hop_per_address_family(
524 tgen
, "r3", "r1", addr_type
, NEXT_HOP_IP_1
526 next_hop2
= next_hop_per_address_family(
527 tgen
, "r3", "r4", addr_type
, NEXT_HOP_IP_2
530 input_topo
= {key
: topo
["routers"][key
] for key
in ["r1"]}
531 result
= verify_bgp_rib(
532 tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
, next_hop2
]
534 assert result
is True, "Test case {} : Failed \n Error: {}".format(
538 result
= verify_rib(tgen
, addr_type
, dut
, input_topo
, next_hop
=next_hop2
)
539 assert result
is True, "Test case {} : Failed \n Error: {}".format(
543 step("Restart daemons and frr services")
545 for daemon
in ["bgpd", "zebra", "staticd", "frr"]:
547 kill_router_daemons(tgen
, "r3", ["staticd"])
548 start_router_daemons(tgen
, "r3", ["staticd"])
550 stop_router(tgen
, "r3")
551 start_router(tgen
, "r3")
554 "Verify BGP convergence on R3 and ensure all the neighbours state "
558 result
= verify_bgp_convergence(tgen
, topo
)
559 assert result
is True, "Test case {} : Failed \n Error: {}".format(
563 step("Verify BGP routes on R3:")
564 step("local pref for routes coming from R1 is set to 0.")
566 for addr_type
in ADDR_TYPES
:
567 rmap_dict
= {"r1": {"route_maps": {"GSHUT-OUT": [{"set": {"locPrf": 0}}]}}}
569 static_routes
= [NETWORK
[addr_type
]]
570 result
= verify_bgp_attributes(
571 tgen
, addr_type
, dut
, static_routes
, "GSHUT-OUT", rmap_dict
573 assert result
is True, "Test case {} : Failed \n Error: {}".format(
577 step("Ensure that best path is selected from R4 to R3.")
579 for addr_type
in ADDR_TYPES
:
581 next_hop1
= next_hop_per_address_family(
582 tgen
, "r3", "r1", addr_type
, NEXT_HOP_IP_1
584 next_hop2
= next_hop_per_address_family(
585 tgen
, "r3", "r4", addr_type
, NEXT_HOP_IP_2
588 input_topo
= {key
: topo
["routers"][key
] for key
in ["r1"]}
589 result
= verify_bgp_rib(
590 tgen
, addr_type
, dut
, input_topo
, next_hop
=[next_hop1
, next_hop2
]
592 assert result
is True, "Test case {} : Failed \n Error: {}".format(
596 result
= verify_rib(tgen
, addr_type
, dut
, input_topo
, next_hop
=next_hop2
)
597 assert result
is True, "Test case {} : Failed \n Error: {}".format(
601 write_test_footer(tc_name
)
604 if __name__
== "__main__":
605 args
= ["-s"] + sys
.argv
[1:]
606 sys
.exit(pytest
.main(args
))