]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/bgp_gr_functionality_topo3/bgp_gr_functionality_topo3.py
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / tests / topotests / bgp_gr_functionality_topo3 / bgp_gr_functionality_topo3.py
CommitLineData
771ac547 1#!/usr/bin/env python
acddc0ed 2# SPDX-License-Identifier: ISC
771ac547
A
3#
4# Copyright (c) 2019 by VMware, Inc. ("VMware")
5# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF")
6# in this file.
7#
771ac547
A
8
9import os
10import sys
11import time
12import pytest
13from time import sleep
14
15import traceback
16import ipaddress
17
18# Save the Current Working Directory to find configuration files.
19CWD = os.path.dirname(os.path.realpath(__file__))
20sys.path.append(os.path.join("../"))
21sys.path.append(os.path.join("../lib/"))
22
23# pylint: disable=C0413
24# Import topogen and topotest helpers
25from lib.topogen import Topogen, get_topogen
26from lib.topolog import logger
27
28# Required to instantiate the topology builder class.
29
30# Import topoJson from lib, to create topology and initial configuration
31from lib.topojson import build_config_from_json
32from lib.bgp import (
33 clear_bgp,
34 verify_bgp_rib,
35 verify_graceful_restart,
36 create_router_bgp,
37 verify_r_bit,
38 verify_eor,
39 verify_f_bit,
40 verify_bgp_convergence,
41 verify_gr_address_family,
42 modify_bgp_config_when_bgpd_down,
43 verify_graceful_restart_timers,
44 verify_bgp_convergence_from_running_config,
45)
84ab3836 46
771ac547 47# Import common_config to use commomnly used APIs
84ab3836
KK
48from lib.common_config import (
49 create_common_configuration,
50 InvalidCLIError,
51 retry,
52 generate_ips,
53 FRRCFG_FILE,
54 find_interface_with_greater_ip,
55 check_address_types,
56 validate_ip_address,
57 run_frr_cmd,
58 get_frr_ipv6_linklocal,
59)
771ac547
A
60
61from lib.common_config import (
62 write_test_header,
63 reset_config_on_routers,
64 start_topology,
65 kill_router_daemons,
66 start_router_daemons,
67 verify_rib,
68 check_address_types,
69 write_test_footer,
70 check_router_status,
71 step,
72 get_frr_ipv6_linklocal,
73 create_static_routes,
74 required_linux_kernel_version,
75)
76
77pytestmark = [pytest.mark.bgpd]
78
79
80# Global variables
81BGP_CONVERGENCE = False
82GR_RESTART_TIMER = 5
83GR_SELECT_DEFER_TIMER = 5
84GR_STALEPATH_TIMER = 5
85# Global variables
86# STATIC_ROUTES=[]
87NETWORK1_1 = {"ipv4": "192.0.2.1/32", "ipv6": "2001:DB8::1:1/128"}
88NETWORK1_2 = {"ipv4": "192.0.2.2/32", "ipv6": "2001:DB8::2:1/128"}
89NETWORK2_1 = {"ipv4": "192.0.2.3/32", "ipv6": "2001:DB8::3:1/128"}
90NETWORK2_2 = {"ipv4": "192.0.2.4/32", "ipv6": "2001:DB8::4:1/128"}
91NETWORK3_1 = {"ipv4": "192.0.2.5/32", "ipv6": "2001:DB8::5:1/128"}
92NETWORK3_2 = {"ipv4": "192.0.2.6/32", "ipv6": "2001:DB8::6:1/128"}
93NETWORK4_1 = {"ipv4": "192.0.2.7/32", "ipv6": "2001:DB8::7:1/128"}
94NETWORK4_2 = {"ipv4": "192.0.2.8/32", "ipv6": "2001:DB8::8:1/128"}
95NETWORK5_1 = {"ipv4": "192.0.2.9/32", "ipv6": "2001:DB8::9:1/128"}
96NETWORK5_2 = {"ipv4": "192.0.2.10/32", "ipv6": "2001:DB8::10:1/128"}
97
98NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"}
99
100PREFERRED_NEXT_HOP = "link_local"
101
102
84ab3836 103def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
771ac547
A
104 """
105 result = configure_gr_followed_by_clear(tgen, topo, dut)
106 assert result is True, \
107 "Testcase {} :Failed \n Error {}". \
108 format(tc_name, result)
109 """
110
111 result = create_router_bgp(tgen, topo, input_dict)
84ab3836 112 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
771ac547
A
113 for addr_type in ADDR_TYPES:
114 clear_bgp(tgen, addr_type, dut)
115
116 for addr_type in ADDR_TYPES:
117 clear_bgp(tgen, addr_type, peer)
118
119 result = verify_bgp_convergence_from_running_config(tgen)
120 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
121
122 return True
123
84ab3836 124
771ac547
A
125def verify_stale_routes_list(tgen, addr_type, dut, input_dict):
126 """
127 This API is use verify Stale routes on refering the network with next hop value
128 Parameters
129 ----------
130 * `tgen`: topogen object
131 * `dut`: input dut router name
132 * `addr_type` : ip type ipv4/ipv6
133 * `input_dict` : input dict, has details of static routes
134 Usage
135 -----
136 dut = 'r1'
137 input_dict = {
138 "r3": {
139 "static_routes": [
140
141 {
142 "network": [NETWORK1_1[addr_type]],
143 "no_of_ip": 2,
144 "vrf": "RED"
145 }
146 ]
147 }
148 }
149
150 result = verify_stale_routes_list(tgen, addr_type, dut, input_dict)
151 Returns
152 -------
153 errormsg(str) or True
154 """
155 logger.debug("Entering lib API: verify_stale_routes_list()")
156 router_list = tgen.routers()
157 additional_nexthops_in_required_nhs = []
158 list1 = []
159 list2 = []
160 found_hops = []
161 for routerInput in input_dict.keys():
162 for router, rnode in router_list.items():
163 if router != dut:
164 continue
165 # Verifying RIB routes
166 command = "show bgp"
167 # Static routes
168 sleep(2)
84ab3836
KK
169 logger.info("Checking router {} BGP RIB:".format(dut))
170 if "static_routes" in input_dict[routerInput]:
771ac547
A
171 static_routes = input_dict[routerInput]["static_routes"]
172 for static_route in static_routes:
173 found_routes = []
174 missing_routes = []
175 st_found = False
176 nh_found = False
177 vrf = static_route.setdefault("vrf", None)
178 community = static_route.setdefault("community", None)
84ab3836 179 largeCommunity = static_route.setdefault("largeCommunity", None)
771ac547 180 if vrf:
84ab3836 181 cmd = "{} vrf {} {}".format(command, vrf, addr_type)
771ac547 182 if community:
84ab3836 183 cmd = "{} community {}".format(cmd, community)
771ac547 184 if largeCommunity:
84ab3836 185 cmd = "{} large-community {}".format(cmd, largeCommunity)
771ac547 186 else:
84ab3836 187 cmd = "{} {}".format(command, addr_type)
771ac547
A
188 cmd = "{} json".format(cmd)
189 rib_routes_json = run_frr_cmd(rnode, cmd, isjson=True)
190 # Verifying output dictionary rib_routes_json is not empty
191 if bool(rib_routes_json) == False:
84ab3836
KK
192 errormsg = "[DUT: {}]: No route found in rib of router".format(
193 router
194 )
771ac547
A
195 return errormsg
196 elif "warning" in rib_routes_json:
84ab3836
KK
197 errormsg = "[DUT: {}]: {}".format(
198 router, rib_routes_json["warning"]
199 )
771ac547
A
200 return errormsg
201 network = static_route["network"]
202 if "no_of_ip" in static_route:
203 no_of_ip = static_route["no_of_ip"]
204 else:
205 no_of_ip = 1
206 # Generating IPs for verification
207 ip_list = generate_ips(network, no_of_ip)
208
209 for st_rt in ip_list:
210 st_rt = str(ipaddress.ip_network(st_rt))
211 _addr_type = validate_ip_address(st_rt)
212 if _addr_type != addr_type:
213 continue
214 if st_rt in rib_routes_json["routes"]:
215 st_found = True
216
217 found_routes.append(st_rt)
84ab3836
KK
218 for mnh in range(0, len(rib_routes_json["routes"][st_rt])):
219 found_hops.append(
220 [
221 rib_r["ip"]
222 for rib_r in rib_routes_json["routes"][st_rt][
223 mnh
224 ]["nexthops"]
225 ]
226 )
771ac547
A
227 return found_hops
228 else:
84ab3836 229 return "error msg - no hops found"
771ac547
A
230
231
232def setup_module(mod):
233 """
234 Sets up the pytest environment
235
236 * `mod`: module name
237 """
238
239 # Required linux kernel version for this suite to run.
240 result = required_linux_kernel_version("4.16")
241 if result is not True:
d63c7094 242 pytest.skip("Kernel requirements are not met, kernel version should be >=4.16")
771ac547
A
243
244 global ADDR_TYPES
245
246 testsuite_run_time = time.asctime(time.localtime(time.time()))
247 logger.info("Testsuite start time: {}".format(testsuite_run_time))
248 logger.info("=" * 40)
249
250 logger.info("Running setup_module to create topology")
251
252 # This function initiates the topology build with Topogen...
253 json_file = "{}/bgp_gr_functionality_topo3.json".format(CWD)
254 tgen = Topogen(json_file, mod.__name__)
255 global topo
256 topo = tgen.json_topo
257 # ... and here it calls Mininet initialization functions.
258
259 # Starting topology, create tmp files which are loaded to routers
d60a3f0e 260 # to start daemons and then start routers
771ac547
A
261 start_topology(tgen)
262
263 # Creating configuration from JSON
264 build_config_from_json(tgen, topo)
265
266 # Api call verify whether BGP is converged
267 ADDR_TYPES = check_address_types()
268
269 for addr_type in ADDR_TYPES:
270 BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
271 assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format(
272 BGP_CONVERGENCE
273 )
274
275 logger.info("Running setup_module() done")
276
277
278def teardown_module(mod):
279 """
280 Teardown the pytest environment
281
282 * `mod`: module name
283 """
284
285 logger.info("Running teardown_module to delete topology")
286
287 tgen = get_topogen()
288
289 # Stop toplogy and Remove tmp files
290 tgen.stop_topology()
291
292 logger.info(
293 "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
294 )
295 logger.info("=" * 40)
84ab3836
KK
296
297
771ac547
A
298################################################################################
299#
300# TEST CASES
301#
302################################################################################
303def test_bgp_gr_stale_routes(request):
304 tgen = get_topogen()
305 tc_name = request.node.name
306 write_test_header(tc_name)
307
308 step("Verify the router failures")
309 if tgen.routers_have_failure():
310 check_router_status(tgen)
311
312 step("Creating 5 static Routes in Router R3 with NULL0 as Next hop")
313 for addr_type in ADDR_TYPES:
84ab3836
KK
314 input_dict_1 = {
315 "r3": {
316 "static_routes": [
317 {
318 "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]],
319 "next_hop": NEXT_HOP_IP[addr_type],
320 },
321 {
322 "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]],
323 "next_hop": NEXT_HOP_IP[addr_type],
324 },
325 {
326 "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]],
327 "next_hop": NEXT_HOP_IP[addr_type],
328 },
329 {
330 "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]],
331 "next_hop": NEXT_HOP_IP[addr_type],
332 },
333 {
334 "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]],
335 "next_hop": NEXT_HOP_IP[addr_type],
336 },
337 ]
771ac547 338 }
84ab3836
KK
339 }
340 result = create_static_routes(tgen, input_dict_1)
341 assert result is True, "Testcase {} : Failed \n Error: {}".format(
342 tc_name, result
343 )
771ac547
A
344 step("verifying Created Route at R3 in VRF default")
345 for addr_type in ADDR_TYPES:
84ab3836
KK
346 dut = "r3"
347 input_dict_1 = {"r3": topo["routers"]["r3"]}
771ac547 348 result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
84ab3836
KK
349 assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
350 # done
771ac547
A
351 step("verifying Created Route at R2 in VRF default")
352 for addr_type in ADDR_TYPES:
84ab3836
KK
353 dut = "r2"
354 input_dict_1 = {"r2": topo["routers"]["r2"]}
771ac547 355 result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
84ab3836 356 assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
771ac547
A
357 step("importing vrf RED on R2 under Address Family")
358 for addr_type in ADDR_TYPES:
84ab3836 359 input_import_vrf = {
771ac547
A
360 "r2": {
361 "bgp": [
362 {
363 "local_as": 200,
364 "vrf": "RED",
84ab3836
KK
365 "address_family": {
366 addr_type: {"unicast": {"import": {"vrf": "default"}}}
367 },
771ac547
A
368 }
369 ]
370 }
371 }
84ab3836
KK
372 result = create_router_bgp(tgen, topo, input_import_vrf)
373 assert result is True, "Testcase {} : Failed \n Error: {}".format(
374 tc_name, result
375 )
376 # done
771ac547
A
377 step("verifying static Routes at R2 in VRF RED")
378 for addr_type in ADDR_TYPES:
84ab3836
KK
379 dut = "r2"
380 input_dict_1 = {"r2": topo["routers"]["r2"]}
771ac547 381 result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
84ab3836 382 assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
771ac547
A
383
384 step("verifying static Routes at R1 in VRF RED")
385 for addr_type in ADDR_TYPES:
84ab3836
KK
386 dut = "r1"
387 input_dict_1 = {"r1": topo["routers"]["r1"]}
771ac547 388 result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
84ab3836 389 assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
771ac547
A
390
391 step("Configuring Graceful restart at R2 and R3 ")
392 input_dict = {
393 "r2": {
771ac547
A
394 "bgp": {
395 "local_as": "200",
396 "graceful-restart": {
397 "graceful-restart": True,
84ab3836 398 },
771ac547
A
399 }
400 },
401 "r3": {
84ab3836
KK
402 "bgp": {"local_as": "300", "graceful-restart": {"graceful-restart": True}}
403 },
771ac547
A
404 }
405
84ab3836 406 configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r2", peer="r3")
771ac547
A
407
408 step("verify Graceful restart at R2")
409 for addr_type in ADDR_TYPES:
84ab3836
KK
410 result = verify_graceful_restart(
411 tgen, topo, addr_type, input_dict, dut="r2", peer="r3"
412 )
413 assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
771ac547
A
414
415 step("verify Graceful restart at R3")
416 for addr_type in ADDR_TYPES:
84ab3836
KK
417 result = verify_graceful_restart(
418 tgen, topo, addr_type, input_dict, dut="r3", peer="r2"
419 )
420 assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
771ac547
A
421
422 step("Configuring Graceful-restart-disable at R3")
423 input_dict = {
424 "r2": {
771ac547
A
425 "bgp": {
426 "local_as": "200",
427 "graceful-restart": {
428 "graceful-restart": False,
84ab3836 429 },
771ac547
A
430 }
431 },
432 "r3": {
84ab3836
KK
433 "bgp": {"local_as": "300", "graceful-restart": {"graceful-restart": False}}
434 },
771ac547 435 }
84ab3836 436 configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r3", peer="r2")
771ac547
A
437
438 step("Verify Graceful-restart-disable at R3")
439 for addr_type in ADDR_TYPES:
84ab3836
KK
440 result = verify_graceful_restart(
441 tgen, topo, addr_type, input_dict, dut="r3", peer="r2"
442 )
443 assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
771ac547
A
444
445 for iteration in range(5):
446 step("graceful-restart-disable:True at R3")
447 input_dict = {
84ab3836
KK
448 "r3": {
449 "bgp": {
450 "graceful-restart": {
451 "graceful-restart-disable": True,
452 }
771ac547
A
453 }
454 }
771ac547 455 }
84ab3836
KK
456 configure_gr_followed_by_clear(
457 tgen, topo, input_dict, tc_name, dut="r3", peer="r2"
458 )
771ac547
A
459
460 step("Verifying Routes at R2 on enabling GRD")
84ab3836 461 dut = "r2"
771ac547 462 for addr_type in ADDR_TYPES:
84ab3836 463 input_dict_1 = {"r2": topo["routers"]["r2"]}
771ac547 464 result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
84ab3836
KK
465 assert result is True, "Testcase {} :Failed \n Error {}".format(
466 tc_name, result
467 )
771ac547
A
468
469 step("Verify stale Routes in Router R2 enabling GRD")
470 for addr_type in ADDR_TYPES:
471 dut = "r2"
472 protocol = "bgp"
473 verify_nh_for_static_rtes = {
474 "r3": {
475 "static_routes": [
771ac547
A
476 {
477 "network": [NETWORK1_1[addr_type]],
478 "no_of_ip": 2,
84ab3836 479 "vrf": "RED",
771ac547
A
480 }
481 ]
482 }
483 }
484 bgp_rib_next_hops = verify_stale_routes_list(
84ab3836
KK
485 tgen, addr_type, dut, verify_nh_for_static_rtes
486 )
487 assert (
488 len(bgp_rib_next_hops) == 1
489 ) is True, "Testcase {} : Failed \n Error: {}".format(
490 tc_name, bgp_rib_next_hops, expected=True
491 )
771ac547
A
492
493 step("graceful-restart-disable:False at R3")
494 input_dict = {
84ab3836
KK
495 "r3": {
496 "bgp": {
497 "graceful-restart": {
498 "graceful-restart-disable": False,
499 }
771ac547
A
500 }
501 }
771ac547 502 }
84ab3836
KK
503 configure_gr_followed_by_clear(
504 tgen, topo, input_dict, tc_name, dut="r3", peer="r2"
505 )
771ac547
A
506
507 step("Verifying Routes at R2 on disabling GRD")
84ab3836 508 dut = "r2"
771ac547 509 for addr_type in ADDR_TYPES:
84ab3836 510 input_dict_1 = {"r2": topo["routers"]["r2"]}
771ac547 511 result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
84ab3836
KK
512 assert result is True, "Testcase {} :Failed \n Error {}".format(
513 tc_name, result
514 )
771ac547
A
515
516 step("Verify stale Routes in Router R2 on disabling GRD")
517 for addr_type in ADDR_TYPES:
518 dut = "r2"
519 protocol = "bgp"
520 verify_nh_for_static_rtes = {
521 "r3": {
522 "static_routes": [
771ac547
A
523 {
524 "network": [NETWORK1_1[addr_type]],
525 "no_of_ip": 2,
84ab3836 526 "vrf": "RED",
771ac547
A
527 }
528 ]
529 }
530 }
84ab3836
KK
531 bgp_rib_next_hops = verify_stale_routes_list(
532 tgen, addr_type, dut, verify_nh_for_static_rtes
533 )
534
535 stale_route_status = len(bgp_rib_next_hops) == 1
536 assert (
537 stale_route_status is True
538 ), "Testcase {} : Failed \n Error: {}".format(
539 tc_name, stale_route_status, expected=True
540 )
771ac547 541 write_test_footer(tc_name)