4 # Copyright (c) 2020 by VMware, Inc. ("VMware")
5 # Used Copyright (c) 2018 by Network Device Education Foundation,
6 # Inc. ("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
23 -Verify static route ECMP functionality with 8 next hop
25 -Verify static route functionality with 8 next hop different AD value
27 -Verify static route with tag option
29 -Verify BGP did not install the static route when it receive route
41 # Save the Current Working Directory to find configuration files.
42 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
43 sys
.path
.append(os
.path
.join(CWD
, "../"))
44 sys
.path
.append(os
.path
.join(CWD
, "../lib/"))
45 # pylint: disable=C0413
46 # Import topogen and topotest helpers
47 from lib
.topogen
import Topogen
, get_topogen
48 from lib
.topotest
import version_cmp
50 from lib
.common_config
import (
54 reset_config_on_routers
,
59 shutdown_bringup_interface
,
63 from lib
.topolog
import logger
64 from lib
.bgp
import verify_bgp_convergence
, create_router_bgp
, verify_bgp_rib
65 from lib
.topojson
import build_config_from_json
67 pytestmark
= [pytest
.mark
.bgpd
, pytest
.mark
.staticd
]
70 BGP_CONVERGENCE
= False
71 ADDR_TYPES
= check_address_types()
94 PREFIX1
= {"ipv4": "110.0.20.1/32", "ipv6": "20::1/128"}
95 NETWORK2
= {"ipv4": ["11.0.20.1/32"], "ipv6": ["2::1/128"]}
99 def setup_module(mod
):
102 Set up the pytest environment.
106 testsuite_run_time
= time
.asctime(time
.localtime(time
.time()))
107 logger
.info("Testsuite start time: {}".format(testsuite_run_time
))
108 logger
.info("=" * 40)
110 logger
.info("Running setup_module to create topology")
112 # This function initiates the topology build with Topogen...
113 json_file
= "{}/static_routes_topo3_ibgp.json".format(CWD
)
114 tgen
= Topogen(json_file
, mod
.__name
__)
116 topo
= tgen
.json_topo
117 # ... and here it calls Mininet initialization functions.
119 # Starting topology, create tmp files which are loaded to routers
120 # to start daemons and then start routers
123 # Creating configuration from JSON
124 build_config_from_json(tgen
, topo
)
126 if version_cmp(platform
.release(), "4.19") < 0:
128 'These tests will not run. (have kernel "{}", '
129 "requires kernel >= 4.19)".format(platform
.release())
131 pytest
.skip(error_msg
)
133 # Checking BGP convergence
134 global BGP_CONVERGENCE
137 # Don't run this test if we have any failure.
138 if tgen
.routers_have_failure():
139 pytest
.skip(tgen
.errors
)
140 # Api call verify whether BGP is converged
141 BGP_CONVERGENCE
= verify_bgp_convergence(tgen
, topo
)
142 assert BGP_CONVERGENCE
is True, "setup_module :Failed \n Error: {}".format(
146 logger
.info("Running setup_module() done")
149 def teardown_module(mod
):
151 Teardown the pytest environment
156 logger
.info("Running teardown_module to delete topology")
160 # Stop toplogy and Remove tmp files
164 "Testsuite end time: {}".format(time
.asctime(time
.localtime(time
.time())))
166 logger
.info("=" * 40)
172 "ipv4": topo
["routers"]["r1"]["links"]["r2-link0"]["ipv4"].split("/")[0],
173 "ipv6": topo
["routers"]["r1"]["links"]["r2-link0"]["ipv6"].split("/")[0],
176 "ipv4": topo
["routers"]["r1"]["links"]["r2-link1"]["ipv4"].split("/")[0],
177 "ipv6": topo
["routers"]["r1"]["links"]["r2-link1"]["ipv6"].split("/")[0],
180 "ipv4": topo
["routers"]["r1"]["links"]["r2-link2"]["ipv4"].split("/")[0],
181 "ipv6": topo
["routers"]["r1"]["links"]["r2-link2"]["ipv6"].split("/")[0],
184 "ipv4": topo
["routers"]["r1"]["links"]["r2-link3"]["ipv4"].split("/")[0],
185 "ipv6": topo
["routers"]["r1"]["links"]["r2-link3"]["ipv6"].split("/")[0],
188 "ipv4": topo
["routers"]["r1"]["links"]["r2-link4"]["ipv4"].split("/")[0],
189 "ipv6": topo
["routers"]["r1"]["links"]["r2-link4"]["ipv6"].split("/")[0],
192 "ipv4": topo
["routers"]["r1"]["links"]["r2-link5"]["ipv4"].split("/")[0],
193 "ipv6": topo
["routers"]["r1"]["links"]["r2-link5"]["ipv6"].split("/")[0],
196 "ipv4": topo
["routers"]["r1"]["links"]["r2-link6"]["ipv4"].split("/")[0],
197 "ipv6": topo
["routers"]["r1"]["links"]["r2-link6"]["ipv6"].split("/")[0],
200 "ipv4": topo
["routers"]["r1"]["links"]["r2-link7"]["ipv4"].split("/")[0],
201 "ipv6": topo
["routers"]["r1"]["links"]["r2-link7"]["ipv6"].split("/")[0],
207 #####################################################
211 #####################################################
214 def test_staticroute_with_ecmp_p0_tc3_ibgp(request
):
216 Verify static route ECMP functionality with 8 next hop'
219 tc_name
= request
.node
.name
220 write_test_header(tc_name
)
223 # Don't run this test if we have any failure.
224 if tgen
.routers_have_failure():
225 pytest
.skip(tgen
.errors
)
227 reset_config_on_routers(tgen
)
228 NEXT_HOP_IP
= populate_nh()
230 step("Configure 8 interfaces / links between R1 and R2,")
232 "Configure IPv4 static route in R2 with 8 next hop"
233 "N1(21.1.1.2), N2(22.1.1.2), N3(23.1.1.2), N4(24.1.1.2),"
234 "N5(25.1.1.2), N6(26.1.1.2), N7(27.1.1.2),N8(28.1.1.2), Static"
235 "route next-hop present on R1"
238 step("Configure IBGP IPv4 peering between R2 and R3 router.")
240 for addr_type
in ADDR_TYPES
:
241 # Enable static routes
242 for nhp
in range(1, 9):
247 "network": PREFIX1
[addr_type
],
248 "next_hop": NEXT_HOP_IP
["nh" + str(nhp
)][addr_type
],
253 logger
.info("Configure static routes")
254 result
= create_static_routes(tgen
, input_dict_4
)
255 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
258 logger
.info("Verifying %s routes on r2", addr_type
)
260 NEXT_HOP_IP
["nh1"][addr_type
],
261 NEXT_HOP_IP
["nh2"][addr_type
],
262 NEXT_HOP_IP
["nh3"][addr_type
],
263 NEXT_HOP_IP
["nh4"][addr_type
],
264 NEXT_HOP_IP
["nh5"][addr_type
],
265 NEXT_HOP_IP
["nh6"][addr_type
],
266 NEXT_HOP_IP
["nh7"][addr_type
],
267 NEXT_HOP_IP
["nh8"][addr_type
],
273 tgen
, addr_type
, dut
, input_dict_4
, next_hop
=nh
, protocol
=protocol
277 ), "Testcase {} : Failed \nError: Routes are missing in RIB".format(tc_name
)
278 step("Configure redistribute static in BGP on R2 router")
279 for addr_type
in ADDR_TYPES
:
285 "unicast": {"redistribute": [{"redist_type": "static"}]}
291 result
= create_router_bgp(tgen
, topo
, input_dict_2
)
292 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
297 "Remove the static route configured with nexthop N1 to N8, one"
298 "by one from running config"
300 for addr_type
in ADDR_TYPES
:
301 # delete static routes
302 for nhp
in range(1, 9):
307 "network": PREFIX1
[addr_type
],
308 "next_hop": NEXT_HOP_IP
["nh" + str(nhp
)][addr_type
],
315 logger
.info("Configure static routes")
316 result
= create_static_routes(tgen
, input_dict_4
)
317 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
332 ), "Testcase {} : Failed \nError: Routes are still present in RIB".format(
336 step("Configure the static route with nexthop N1 to N8, one by one")
338 for addr_type
in ADDR_TYPES
:
340 for nhp
in range(1, 9):
345 "network": PREFIX1
[addr_type
],
346 "next_hop": NEXT_HOP_IP
["nh" + str(nhp
)][addr_type
],
352 logger
.info("Configure static routes")
353 result
= create_static_routes(tgen
, input_dict_4
)
354 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
359 tgen
, addr_type
, dut
, input_dict_4
, next_hop
=nh
, protocol
=protocol
363 ), "Testcase {} : Failed \nError: Routes are missing in RIB".format(tc_name
)
365 step("Random shut of the nexthop interfaces")
366 randnum
= random
.randint(0, 7)
367 for addr_type
in ADDR_TYPES
:
368 intf
= topo
["routers"]["r2"]["links"]["r1-link" + str(randnum
)]["interface"]
369 shutdown_bringup_interface(tgen
, dut
, intf
, False)
370 nhip
= NEXT_HOP_IP
["nh" + str(randnum
+ 1)][addr_type
]
375 "network": PREFIX1
[addr_type
],
376 "next_hop": NEXT_HOP_IP
["nh" + str(randnum
+ 1)][addr_type
],
392 ), "Testcase {} : Failed \n Error: Routes are still present in RIB".format(
396 step("Random no shut of the nexthop interfaces")
397 for addr_type
in ADDR_TYPES
:
398 intf
= topo
["routers"]["r2"]["links"]["r1-link" + str(randnum
)]["interface"]
399 shutdown_bringup_interface(tgen
, dut
, intf
, True)
400 nhip
= NEXT_HOP_IP
["nh" + str(randnum
+ 1)][addr_type
]
402 tgen
, addr_type
, dut
, input_dict_5
, next_hop
=nhip
, protocol
=protocol
406 ), "Testcase {} : Failed \n Error: Routes are missing in RIB".format(tc_name
)
408 step("Reload the FRR router")
409 # stop/start -> restart FRR router and verify
410 stop_router(tgen
, "r2")
411 start_router(tgen
, "r2")
414 tgen
, addr_type
, dut
, input_dict_4
, next_hop
=nh
, protocol
=protocol
418 ), "Testcase {} : Failed \nError: Routes are missing in RIB".format(tc_name
)
420 write_test_footer(tc_name
)
423 def test_staticroute_with_ecmp_with_diff_AD_p0_tc4_ibgp(request
):
425 Verify static route ECMP functionality with 8 next hop
428 tc_name
= request
.node
.name
429 write_test_header(tc_name
)
432 # Don't run this test if we have any failure.
433 if tgen
.routers_have_failure():
434 pytest
.skip(tgen
.errors
)
436 reset_config_on_routers(tgen
)
438 step("Configure 8 interfaces / links between R1 and R2,")
439 step("Configure IBGP IPv4 peering between R2 and R3 router.")
440 NEXT_HOP_IP
= populate_nh()
442 for addr_type
in ADDR_TYPES
:
443 nh_all
[addr_type
] = []
444 for nhp
in range(1, 9):
445 nh_all
[addr_type
].append(NEXT_HOP_IP
["nh" + str(nhp
)][addr_type
])
447 "Configure IPv4 static route in R2 with 8 next hop"
448 "N1(21.1.1.2) AD 10, N2(22.1.1.2) AD 20, N3(23.1.1.2) AD 30,"
449 "N4(24.1.1.2) AD 40, N5(25.1.1.2) AD 50, N6(26.1.1.2) AD 60,"
450 "N7(27.1.1.2) AD 70, N8(28.1.1.2) AD 80, Static route next-hop"
453 for addr_type
in ADDR_TYPES
:
454 for nhp
in range(1, 9):
459 "network": PREFIX1
[addr_type
],
460 "next_hop": NEXT_HOP_IP
["nh" + str(nhp
)][addr_type
],
461 "admin_distance": 10 * nhp
,
466 logger
.info("Configure static routes")
467 result
= create_static_routes(tgen
, input_dict_4
)
468 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
471 logger
.info("Verifying %s routes on r2", addr_type
)
474 "On R2, static route installed in RIB using "
475 "show ip route with 8 next hop, lowest AD nexthop is active"
477 step("On R2, static route with lowest AD nexthop installed in FIB")
482 "network": PREFIX1
[addr_type
],
483 "next_hop": NEXT_HOP_IP
["nh1"][addr_type
],
484 "admin_distance": 10,
491 nh
= NEXT_HOP_IP
["nh1"][addr_type
]
493 tgen
, addr_type
, dut
, input_dict_4
, next_hop
=nh
, protocol
=protocol
, fib
=True
495 assert result
is True, (
496 "Testcase {} : Failed \nError: Route with "
497 " lowest AD is missing in RIB".format(tc_name
)
501 for nhp
in range(2, 9):
502 nh
.append(NEXT_HOP_IP
["nh" + str(nhp
)][addr_type
])
513 assert result
is not True, (
514 "Testcase {} : Failed \nError: Routes "
515 " with high AD are active in RIB".format(tc_name
)
518 step("Configure redistribute static in BGP on R2 router")
519 for addr_type
in ADDR_TYPES
:
525 "unicast": {"redistribute": [{"redist_type": "static"}]}
532 logger
.info("Configuring redistribute static")
533 result
= create_router_bgp(tgen
, topo
, input_dict_2
)
534 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
539 "After configuring them, route is always active with lowest AD"
540 "value and all the nexthop populated in RIB and FIB again "
546 "network": PREFIX1
[addr_type
],
547 "next_hop": NEXT_HOP_IP
["nh1"][addr_type
],
548 "admin_distance": 10,
555 nh
= NEXT_HOP_IP
["nh1"][addr_type
]
557 tgen
, addr_type
, dut
, input_dict_4
, next_hop
=nh
, protocol
=protocol
, fib
=True
559 assert result
is True, (
560 "Testcase {} : Failed \nError: Route with "
561 " lowest AD is missing in RIB".format(tc_name
)
565 "Remove the static route configured with nexthop N1 to N8, one"
566 "by one from running config"
569 for addr_type
in ADDR_TYPES
:
570 # delete static routes
571 for nhp
in range(1, 9):
576 "network": PREFIX1
[addr_type
],
577 "next_hop": NEXT_HOP_IP
["nh" + str(nhp
)][addr_type
],
578 "admin_distance": 10 * nhp
,
585 logger
.info("Configure static routes")
586 result
= create_static_routes(tgen
, input_dict_4
)
587 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
592 "After removing the static route with N1 to N8 one by one, "
593 "route become active with next preferred nexthop and nexthop which "
594 "got removed is not shown in RIB and FIB"
601 next_hop
=nh_all
[addr_type
],
607 ), "Testcase {} : Failed \nError: Routes are still present in RIB".format(tc_name
)
609 step("Configure the static route with nexthop N1 to N8, one by one")
610 for addr_type
in ADDR_TYPES
:
612 for nhp
in range(1, 9):
617 "network": PREFIX1
[addr_type
],
618 "next_hop": NEXT_HOP_IP
["nh" + str(nhp
)][addr_type
],
619 "admin_distance": 10 * nhp
,
624 logger
.info("Configure static routes")
625 result
= create_static_routes(tgen
, input_dict_4
)
626 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
630 step("On R2, static route with lowest AD nexthop installed in FIB")
635 "network": PREFIX1
[addr_type
],
636 "next_hop": NEXT_HOP_IP
["nh1"][addr_type
],
637 "admin_distance": 10,
644 nh
= NEXT_HOP_IP
["nh1"][addr_type
]
646 tgen
, addr_type
, dut
, input_dict_4
, next_hop
=nh
, protocol
=protocol
, fib
=True
648 assert result
is True, (
649 "Testcase {} : Failed \nError: Route with "
650 " lowest AD is missing in RIB".format(tc_name
)
654 for nhp
in range(2, 9):
655 nh
.append(NEXT_HOP_IP
["nh" + str(nhp
)][addr_type
])
666 assert result
is not True, (
667 "Testcase {} : Failed \nError: Routes "
668 " with high AD are active in RIB".format(tc_name
)
671 step("Random shut of the nexthop interfaces")
672 randnum
= random
.randint(0, 7)
673 for addr_type
in ADDR_TYPES
:
674 intf
= topo
["routers"]["r2"]["links"]["r1-link" + str(randnum
)]["interface"]
675 shutdown_bringup_interface(tgen
, dut
, intf
, False)
676 nhip
= NEXT_HOP_IP
["nh" + str(randnum
+ 1)][addr_type
]
681 "network": PREFIX1
[addr_type
],
682 "next_hop": NEXT_HOP_IP
["nh" + str(randnum
+ 1)][addr_type
],
698 ), "Testcase {} : Failed \n Error: Routes are still present in RIB".format(
702 step("Random no shut of the nexthop interfaces")
703 for addr_type
in ADDR_TYPES
:
704 intf
= topo
["routers"]["r2"]["links"]["r1-link" + str(randnum
)]["interface"]
705 shutdown_bringup_interface(tgen
, dut
, intf
, True)
706 nhip
= NEXT_HOP_IP
["nh" + str(randnum
+ 1)][addr_type
]
708 tgen
, addr_type
, dut
, input_dict_5
, next_hop
=nhip
, protocol
=protocol
712 ), "Testcase {} : Failed \n Error: Routes are missing in RIB".format(tc_name
)
714 step("Reload the FRR router")
715 # stop/start -> restart FRR router and verify
716 stop_router(tgen
, "r2")
717 start_router(tgen
, "r2")
720 "After reload of FRR router, static route installed "
721 "in RIB and FIB properly ."
723 for addr_type
in ADDR_TYPES
:
728 "network": PREFIX1
[addr_type
],
729 "next_hop": NEXT_HOP_IP
["nh1"][addr_type
],
730 "admin_distance": 10,
737 nh
= NEXT_HOP_IP
["nh1"][addr_type
]
739 tgen
, addr_type
, dut
, input_dict_4
, next_hop
=nh
, protocol
=protocol
, fib
=True
741 assert result
is True, (
742 "Testcase {} : Failed \nError: Route with "
743 " lowest AD is missing in RIB".format(tc_name
)
747 for nhp
in range(2, 9):
748 nh
.append(NEXT_HOP_IP
["nh" + str(nhp
)][addr_type
])
759 assert result
is not True, (
760 "Testcase {} : Failed \nError: Routes "
761 " with high AD are active in RIB".format(tc_name
)
764 step("Remove the redistribute static knob")
766 for addr_type
in ADDR_TYPES
:
774 {"redist_type": "static", "delete": True}
783 logger
.info("Remove redistribute static")
784 result
= create_router_bgp(tgen
, topo
, input_dict_2
)
785 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
788 step("verify that routes are deleted from R3 routing table")
800 assert result
is not True, (
801 "Testcase {} : Failed \nError: Routes are"
802 " still present in RIB of R3".format(tc_name
)
805 write_test_footer(tc_name
)
808 def test_bgp_local_nexthop_p1_tc14_ibgp(request
):
810 Verify BGP did not install the static route when it receive route
814 tc_name
= request
.node
.name
815 write_test_header(tc_name
)
818 step("Configure BGP IPv4 session between R2 and R3")
819 step("Configure IPv4 static route on R2")
820 reset_config_on_routers(tgen
)
822 for addr_type
in ADDR_TYPES
:
823 # Enable static routes
828 "network": NETWORK
[addr_type
],
829 "next_hop": topo
["routers"]["r3"]["links"]["r2-link0"][
837 logger
.info("Configure static routes")
838 result
= create_static_routes(tgen
, input_dict_4
)
839 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
843 step("Configure redistribute static in the BGP")
850 "unicast": {"redistribute": [{"redist_type": "static"}]}
856 result
= create_router_bgp(tgen
, topo
, input_dict_2
)
857 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
861 step("Verify R2 BGP table has IPv4 route")
863 result
= verify_rib(tgen
, addr_type
, dut
, input_dict_4
)
866 ), "Testcase {} : Failed \nError: routes are missing in RIB of R2".format(
870 step(" Verify route did not install in the R3 BGP table, RIB/FIB")
872 result
= verify_bgp_rib(tgen
, addr_type
, dut
, input_dict_4
, expected
=False)
873 assert result
is not True, (
874 "Testcase {} : Failed \nError: routes are"
875 " still present in BGP RIB of R2".format(tc_name
)
878 result
= verify_rib(tgen
, addr_type
, dut
, input_dict_4
, expected
=False)
879 assert result
is not True, (
880 "Testcase {} : Failed \nError: routes are"
881 " still present in RIB of R2".format(tc_name
)
884 write_test_footer(tc_name
)
887 if __name__
== "__main__":
888 args
= ["-s"] + sys
.argv
[1:]
889 sys
.exit(pytest
.main(args
))