]>
Commit | Line | Data |
---|---|---|
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 | |
9 | import os | |
10 | import sys | |
11 | import time | |
12 | import pytest | |
13 | from time import sleep | |
14 | ||
15 | import traceback | |
16 | import ipaddress | |
17 | ||
18 | # Save the Current Working Directory to find configuration files. | |
19 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
20 | sys.path.append(os.path.join("../")) | |
21 | sys.path.append(os.path.join("../lib/")) | |
22 | ||
23 | # pylint: disable=C0413 | |
24 | # Import topogen and topotest helpers | |
25 | from lib.topogen import Topogen, get_topogen | |
26 | from 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 | |
31 | from lib.topojson import build_config_from_json | |
32 | from 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 |
48 | from 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 | |
61 | from 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 | ||
77 | pytestmark = [pytest.mark.bgpd] | |
78 | ||
79 | ||
80 | # Global variables | |
81 | BGP_CONVERGENCE = False | |
82 | GR_RESTART_TIMER = 5 | |
83 | GR_SELECT_DEFER_TIMER = 5 | |
84 | GR_STALEPATH_TIMER = 5 | |
85 | # Global variables | |
86 | # STATIC_ROUTES=[] | |
87 | NETWORK1_1 = {"ipv4": "192.0.2.1/32", "ipv6": "2001:DB8::1:1/128"} | |
88 | NETWORK1_2 = {"ipv4": "192.0.2.2/32", "ipv6": "2001:DB8::2:1/128"} | |
89 | NETWORK2_1 = {"ipv4": "192.0.2.3/32", "ipv6": "2001:DB8::3:1/128"} | |
90 | NETWORK2_2 = {"ipv4": "192.0.2.4/32", "ipv6": "2001:DB8::4:1/128"} | |
91 | NETWORK3_1 = {"ipv4": "192.0.2.5/32", "ipv6": "2001:DB8::5:1/128"} | |
92 | NETWORK3_2 = {"ipv4": "192.0.2.6/32", "ipv6": "2001:DB8::6:1/128"} | |
93 | NETWORK4_1 = {"ipv4": "192.0.2.7/32", "ipv6": "2001:DB8::7:1/128"} | |
94 | NETWORK4_2 = {"ipv4": "192.0.2.8/32", "ipv6": "2001:DB8::8:1/128"} | |
95 | NETWORK5_1 = {"ipv4": "192.0.2.9/32", "ipv6": "2001:DB8::9:1/128"} | |
96 | NETWORK5_2 = {"ipv4": "192.0.2.10/32", "ipv6": "2001:DB8::10:1/128"} | |
97 | ||
98 | NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"} | |
99 | ||
100 | PREFERRED_NEXT_HOP = "link_local" | |
101 | ||
102 | ||
84ab3836 | 103 | def 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 |
125 | def 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 | ||
232 | def 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 | ||
278 | def 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 | ################################################################################ | |
303 | def 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) |