]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py
*: auto-convert to SPDX License IDs
[mirror_frr.git] / tests / topotests / evpn_type5_test_topo1 / test_evpn_type5_topo1.py
1 #!/usr/bin/env python
2 # SPDX-License-Identifier: ISC
3
4 #
5 # Copyright (c) 2020 by VMware, Inc. ("VMware")
6 # Used Copyright (c) 2018 by Network Device Education Foundation,
7 # Inc. ("NetDEF") in this file.
8 #
9
10 """
11 Following tests are covered to test EVPN-Type5 functionality:
12
13 1. RD verification (manual/auto).
14 2. RT verification(manual)
15 3. In an active/standby EVPN implementation, if active DCG goes down,
16 secondary takes over.
17 4. EVPN routes are advertised/withdrawn, based on VNFs
18 advertising/withdrawing IP prefixes.
19 5. Route-map operations for EVPN address family.
20 6. BGP attributes for EVPN address-family.
21 """
22
23 import os
24 import sys
25 import json
26 import time
27 import pytest
28 import platform
29 from copy import deepcopy
30
31
32 # Save the Current Working Directory to find configuration files.
33 CWD = os.path.dirname(os.path.realpath(__file__))
34 sys.path.append(os.path.join(CWD, "../"))
35 sys.path.append(os.path.join(CWD, "../lib/"))
36
37 # Required to instantiate the topology builder class.
38
39 # pylint: disable=C0413
40 # Import topogen and topotest helpers
41 from lib.topotest import version_cmp
42 from lib.topogen import Topogen, get_topogen
43
44 from lib.common_config import (
45 start_topology,
46 write_test_header,
47 check_address_types,
48 write_test_footer,
49 reset_config_on_routers,
50 verify_rib,
51 step,
52 create_route_maps,
53 create_static_routes,
54 create_vrf_cfg,
55 check_router_status,
56 apply_raw_config,
57 configure_vxlan,
58 configure_brctl,
59 create_interface_in_kernel,
60 kill_router_daemons,
61 start_router_daemons,
62 )
63
64 from lib.topolog import logger
65 from lib.bgp import (
66 verify_bgp_convergence,
67 create_router_bgp,
68 verify_best_path_as_per_bgp_attribute,
69 verify_attributes_for_evpn_routes,
70 verify_evpn_routes,
71 )
72 from lib.topojson import build_topo_from_json, build_config_from_json
73
74 pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
75
76 # Global variables
77 NETWORK1_1 = {"ipv4": "10.1.1.1/32", "ipv6": "10::1/128"}
78 NETWORK1_2 = {"ipv4": "40.1.1.1/32", "ipv6": "40::1/128"}
79 NETWORK1_3 = {"ipv4": "40.1.1.2/32", "ipv6": "40::2/128"}
80 NETWORK1_4 = {"ipv4": "40.1.1.3/32", "ipv6": "40::3/128"}
81 NETWORK2_1 = {"ipv4": "20.1.1.1/32", "ipv6": "20::1/128"}
82 NETWORK3_1 = {"ipv4": "30.1.1.1/32", "ipv6": "30::1/128"}
83 NETWORK4_1 = {"ipv4": "100.1.1.1/32 ", "ipv6": "100::100/128"}
84 NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"}
85 VNI_1 = 75100
86 VNI_2 = 75200
87 VNI_3 = 75300
88 MAC_1 = "00:80:48:ba:d1:00"
89 MAC_2 = "00:80:48:ba:d1:01"
90 MAC_3 = "00:80:48:ba:d1:02"
91 BRCTL_1 = "br100"
92 BRCTL_2 = "br200"
93 BRCTL_3 = "br300"
94 VXLAN_1 = "vxlan75100"
95 VXLAN_2 = "vxlan75200"
96 VXLAN_3 = "vxlan75300"
97 BRIDGE_INTF1 = "120.0.0.1"
98 BRIDGE_INTF2 = "120.0.0.2"
99 BRIDGE_INTF3 = "120.0.0.3"
100
101 VXLAN = {
102 "vxlan_name": [VXLAN_1, VXLAN_2, VXLAN_3],
103 "vxlan_id": [75100, 75200, 75300],
104 "dstport": 4789,
105 "local_addr": {"e1": BRIDGE_INTF1, "d1": BRIDGE_INTF2, "d2": BRIDGE_INTF3},
106 "learning": "no",
107 }
108 BRCTL = {
109 "brctl_name": [BRCTL_1, BRCTL_2, BRCTL_3],
110 "addvxlan": [VXLAN_1, VXLAN_2, VXLAN_3],
111 "vrf": ["RED", "BLUE", "GREEN"],
112 "stp": [0, 0, 0],
113 }
114
115
116 def setup_module(mod):
117 """
118 Sets up the pytest environment
119
120 * `mod`: module name
121 """
122
123 global topo
124 testsuite_run_time = time.asctime(time.localtime(time.time()))
125 logger.info("Testsuite start time: {}".format(testsuite_run_time))
126 logger.info("=" * 40)
127
128 logger.info("Running setup_module to create topology")
129
130 # This function initiates the topology build with Topogen...
131 json_file = "{}/evpn_type5_topo1.json".format(CWD)
132 tgen = Topogen(json_file, mod.__name__)
133 topo = tgen.json_topo
134
135 # ... and here it calls Mininet initialization functions.
136
137 # Starting topology, create tmp files which are loaded to routers
138 # to start daemons and then start routers
139 start_topology(tgen)
140
141 # Creating configuration from JSON
142 build_config_from_json(tgen, topo)
143
144 if version_cmp(platform.release(), "4.19") < 0:
145 error_msg = (
146 'EVPN tests will not run (have kernel "{}", '
147 "but it requires >= 4.19)".format(platform.release())
148 )
149 pytest.skip(error_msg)
150
151 global BGP_CONVERGENCE
152 global ADDR_TYPES
153 ADDR_TYPES = check_address_types()
154
155 BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
156 assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format(
157 BGP_CONVERGENCE
158 )
159
160 logger.info("Pre-requisite config for testsuite")
161 prerequisite_config_for_test_suite(tgen)
162
163 logger.info("Running setup_module() done")
164
165
166 def teardown_module():
167 """Teardown the pytest environment"""
168
169 logger.info("Running teardown_module to delete topology")
170
171 tgen = get_topogen()
172
173 # Stop toplogy and Remove tmp files
174 tgen.stop_topology()
175
176 logger.info(
177 "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
178 )
179 logger.info("=" * 40)
180
181
182 #####################################################
183 #
184 # Testcases
185 #
186 #####################################################
187
188
189 def prerequisite_config_for_test_suite(tgen):
190 """
191 API to do prerequisite config for testsuite
192
193 parameters:
194 -----------
195 * `tgen`: topogen object
196 """
197
198 step("Configure vxlan, bridge interface")
199 for dut in ["e1", "d1", "d2"]:
200 step("[DUT: ]Configure vxlan")
201 vxlan_input = {
202 dut: {
203 "vxlan": [
204 {
205 "vxlan_name": VXLAN["vxlan_name"],
206 "vxlan_id": VXLAN["vxlan_id"],
207 "dstport": VXLAN["dstport"],
208 "local_addr": VXLAN["local_addr"][dut],
209 "learning": VXLAN["learning"],
210 }
211 ]
212 }
213 }
214
215 result = configure_vxlan(tgen, vxlan_input)
216 assert result is True, "Testcase :Failed \n Error: {}".format(result)
217
218 step("Configure bridge interface")
219 brctl_input = {
220 dut: {
221 "brctl": [
222 {
223 "brctl_name": BRCTL["brctl_name"],
224 "addvxlan": BRCTL["addvxlan"],
225 "vrf": BRCTL["vrf"],
226 "stp": BRCTL["stp"],
227 }
228 ]
229 }
230 }
231 result = configure_brctl(tgen, topo, brctl_input)
232 assert result is True, "Testcase :Failed \n Error: {}".format(result)
233
234 step("Configure default routes")
235 add_default_routes(tgen)
236
237
238 def add_default_routes(tgen):
239 """
240 API to do prerequisite config for testsuite
241
242 parameters:
243 -----------
244 * `tgen`: topogen object
245 """
246
247 step("Add default routes..")
248
249 default_routes = {
250 "e1": {
251 "static_routes": [
252 {
253 "network": "{}/32".format(VXLAN["local_addr"]["d1"]),
254 "next_hop": topo["routers"]["d1"]["links"]["e1-link1"][
255 "ipv4"
256 ].split("/")[0],
257 },
258 {
259 "network": "{}/32".format(VXLAN["local_addr"]["d2"]),
260 "next_hop": topo["routers"]["d2"]["links"]["e1-link1"][
261 "ipv4"
262 ].split("/")[0],
263 },
264 ]
265 },
266 "d1": {
267 "static_routes": [
268 {
269 "network": "{}/32".format(VXLAN["local_addr"]["e1"]),
270 "next_hop": topo["routers"]["e1"]["links"]["d1-link1"][
271 "ipv4"
272 ].split("/")[0],
273 },
274 {
275 "network": "{}/32".format(VXLAN["local_addr"]["d2"]),
276 "next_hop": topo["routers"]["e1"]["links"]["d1-link1"][
277 "ipv4"
278 ].split("/")[0],
279 },
280 ]
281 },
282 "d2": {
283 "static_routes": [
284 {
285 "network": "{}/32".format(VXLAN["local_addr"]["d1"]),
286 "next_hop": topo["routers"]["e1"]["links"]["d2-link1"][
287 "ipv4"
288 ].split("/")[0],
289 },
290 {
291 "network": "{}/32".format(VXLAN["local_addr"]["e1"]),
292 "next_hop": topo["routers"]["e1"]["links"]["d2-link1"][
293 "ipv4"
294 ].split("/")[0],
295 },
296 ]
297 },
298 }
299
300 result = create_static_routes(tgen, default_routes)
301 assert result is True, "Testcase :Failed \n Error: {}".format(result)
302
303
304 def test_RD_verification_manual_and_auto_p0(request):
305 """
306 RD verification (manual/auto).
307 """
308
309 tgen = get_topogen()
310 tc_name = request.node.name
311 write_test_header(tc_name)
312 check_router_status(tgen)
313 reset_config_on_routers(tgen)
314 add_default_routes(tgen)
315
316 if tgen.routers_have_failure():
317 pytest.skip(tgen.errors)
318
319 step(
320 "Advertise prefixes from VNF routers R1 and R2 in associated "
321 "VRFs for both address-family."
322 )
323 step(
324 "Advertise vrf RED's routes in EVPN address family from Edge-1 router"
325 ", without manual configuration of RD."
326 )
327
328 for addr_type in ADDR_TYPES:
329 input_dict_1 = {
330 "r1": {
331 "static_routes": [
332 {
333 "network": NETWORK1_1[addr_type],
334 "next_hop": NEXT_HOP_IP[addr_type],
335 "vrf": "RED",
336 }
337 ]
338 },
339 "r2": {
340 "static_routes": [
341 {
342 "network": NETWORK2_1[addr_type],
343 "next_hop": NEXT_HOP_IP[addr_type],
344 "vrf": "BLUE",
345 },
346 {
347 "network": NETWORK3_1[addr_type],
348 "next_hop": NEXT_HOP_IP[addr_type],
349 "vrf": "GREEN",
350 },
351 ]
352 },
353 }
354
355 result = create_static_routes(tgen, input_dict_1)
356 assert result is True, "Testcase {} : Failed \n Error: {}".format(
357 tc_name, result
358 )
359
360 step("Verify on DCG-1 and DCG-2:")
361 step("EVPN route for 10.1.1.1/32 has auto-assigned RD value.")
362
363 for dut in ["d1", "d2"]:
364 input_routes = {key: topo["routers"][key] for key in ["r1"]}
365 result = verify_attributes_for_evpn_routes(
366 tgen, topo, dut, input_routes, rd="auto", rd_peer="e1"
367 )
368 assert result is True, "Testcase {} on {} :Failed \n Error: {}".format(
369 tc_name, dut, result
370 )
371
372 step(
373 "Configure RD for vrf RED manually as 50.50.50.50:50 and "
374 "advertise vrf RED's routes in EVPN address family from "
375 "Edge-1 router."
376 )
377
378 input_dict_rd = {
379 "e1": {
380 "bgp": [
381 {
382 "local_as": "100",
383 "vrf": "RED",
384 "address_family": {"l2vpn": {"evpn": {"rd": "50.50.50.50:50"}}},
385 }
386 ]
387 }
388 }
389
390 result = create_router_bgp(tgen, topo, input_dict_rd)
391 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
392
393 step("EVPN route for vrf RED has RD value as 50.50.50.50:50")
394 for dut in ["d1", "d2"]:
395 input_routes = {key: topo["routers"][key] for key in ["r1"]}
396 result = verify_attributes_for_evpn_routes(
397 tgen, topo, dut, input_routes, rd="50.50.50.50:50"
398 )
399 assert result is True, "Testcase {} on {} :Failed \n Error: {}".format(
400 tc_name, dut, result
401 )
402
403 step(
404 "Configure RD for vrf RED manually as 100.100.100.100:100 and "
405 "advertise vrf RED's routes in EVPN address family from Edge-1 "
406 "router."
407 )
408 input_dict_rd = {
409 "e1": {
410 "bgp": [
411 {
412 "local_as": "100",
413 "vrf": "RED",
414 "address_family": {
415 "l2vpn": {"evpn": {"rd": "100.100.100.100:100"}}
416 },
417 }
418 ]
419 }
420 }
421
422 result = create_router_bgp(tgen, topo, input_dict_rd)
423 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
424
425 step(
426 "EVPN route for vrf RED is overridden with RD value as " "100.100.100.100:100."
427 )
428
429 for dut in ["d1", "d2"]:
430 input_routes = {key: topo["routers"][key] for key in ["r1"]}
431 result = verify_attributes_for_evpn_routes(
432 tgen, topo, dut, input_routes, rd="100.100.100.100:100"
433 )
434 assert result is True, "Testcase {} on {} :Failed \n Error: {}".format(
435 tc_name, dut, result
436 )
437
438 step(
439 "Configure RD for vrf BLUE manually same as vrf RED "
440 "(100.100.100.100:100) and advertise vrf RED and BLUE's routes "
441 "in EVPN address family from Edge-1 router."
442 )
443
444 input_dict_rd = {
445 "e1": {
446 "bgp": [
447 {
448 "local_as": "100",
449 "vrf": "BLUE",
450 "address_family": {
451 "l2vpn": {"evpn": {"rd": "100.100.100.100:100"}}
452 },
453 }
454 ]
455 }
456 }
457
458 result = create_router_bgp(tgen, topo, input_dict_rd)
459 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
460
461 step(
462 "Delete manually configured RD and advertise vrf RED's routes "
463 "in EVPN address family from Edge-1 router."
464 )
465
466 input_dict_rd = {
467 "e1": {
468 "bgp": [
469 {
470 "local_as": "100",
471 "vrf": "RED",
472 "address_family": {
473 "l2vpn": {"evpn": {"no rd": "100.100.100.100:100"}}
474 },
475 }
476 ]
477 }
478 }
479
480 result = create_router_bgp(tgen, topo, input_dict_rd)
481 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
482
483 step(
484 "Configure same RD value for vrf GREEN, as auto generated RD "
485 "value for vrf RED on Edge-1 router."
486 )
487
488 input_dict_rd = {
489 "e1": {
490 "bgp": [
491 {
492 "local_as": "100",
493 "vrf": "GREEN",
494 "address_family": {"l2vpn": {"evpn": {"rd": "10.0.0.33:1"}}},
495 }
496 ]
497 }
498 }
499
500 result = create_router_bgp(tgen, topo, input_dict_rd)
501 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
502
503 step("Delete auto configured RD value from vrf RED in EVPN " "address family.")
504
505 input_dict_rd = {
506 "e1": {
507 "bgp": [
508 {
509 "local_as": "100",
510 "vrf": "GREEN",
511 "address_family": {"l2vpn": {"evpn": {"no rd": "10.0.0.33:1"}}},
512 }
513 ]
514 }
515 }
516
517 result = create_router_bgp(tgen, topo, input_dict_rd)
518 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
519
520 step("Configure RD value as 100.100.100:100")
521
522 input_dict_rd = {
523 "e1": {
524 "bgp": [
525 {
526 "local_as": "100",
527 "vrf": "GREEN",
528 "address_family": {"l2vpn": {"evpn": {"rd": "100.100.100:100"}}},
529 }
530 ]
531 }
532 }
533
534 result = create_router_bgp(tgen, topo, input_dict_rd)
535 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
536
537 write_test_footer(tc_name)
538
539
540 def test_RT_verification_manual_p0(request):
541 """
542 RT verification(manual)
543 """
544
545 tgen = get_topogen()
546 tc_name = request.node.name
547 write_test_header(tc_name)
548 check_router_status(tgen)
549 reset_config_on_routers(tgen)
550 add_default_routes(tgen)
551
552 if tgen.routers_have_failure():
553 pytest.skip(tgen.errors)
554
555 step(
556 "Advertise prefixes from VNF routers R1 and R2 in associated "
557 "VRFs for both address-family."
558 )
559 step("Advertise VRF routes as in EVPN address family from Edge-1 " "router.")
560
561 for addr_type in ADDR_TYPES:
562 input_dict_1 = {
563 "r1": {
564 "static_routes": [
565 {
566 "network": NETWORK1_1[addr_type],
567 "next_hop": NEXT_HOP_IP[addr_type],
568 "vrf": "RED",
569 }
570 ]
571 },
572 "r2": {
573 "static_routes": [
574 {
575 "network": NETWORK2_1[addr_type],
576 "next_hop": NEXT_HOP_IP[addr_type],
577 "vrf": "BLUE",
578 },
579 {
580 "network": NETWORK3_1[addr_type],
581 "next_hop": NEXT_HOP_IP[addr_type],
582 "vrf": "GREEN",
583 },
584 ]
585 },
586 }
587
588 result = create_static_routes(tgen, input_dict_1)
589 assert result is True, "Testcase {} : Failed \n Error: {}".format(
590 tc_name, result
591 )
592
593 step(
594 "Configure RT for vrf RED manually as export 100:100 "
595 "and advertise vrf RED's routes in EVPN address family"
596 " from Edge-1 router."
597 )
598
599 input_dict_rt = {
600 "e1": {
601 "bgp": [
602 {
603 "local_as": "100",
604 "vrf": "RED",
605 "address_family": {
606 "ipv4": {
607 "unicast": {"neighbor": {"r1": {"dest_link": {"e1": {}}}}}
608 },
609 "ipv6": {
610 "unicast": {"neighbor": {"r1": {"dest_link": {"e1": {}}}}}
611 },
612 "l2vpn": {
613 "evpn": {"route-target": {"export": [{"value": "100:100"}]}}
614 },
615 },
616 }
617 ]
618 }
619 }
620
621 result = create_router_bgp(tgen, topo, input_dict_rt)
622 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
623
624 step(
625 "Verify on dcg-1 and dcg-2, EVPN route for 10.1.1.1/32"
626 " and 10::1/128 have RT value as 100:100."
627 )
628
629 for dut in ["d1", "d2"]:
630 input_routes = {key: topo["routers"][key] for key in ["r1"]}
631 result = verify_attributes_for_evpn_routes(
632 tgen, topo, dut, input_routes, rt="100:100"
633 )
634 assert result is True, "Testcase {} on {} :Failed \n Error: {}".format(
635 tc_name, dut, result
636 )
637
638 step(
639 "Configure RT for vrf RED manually as export 500:500 and"
640 " advertise vrf RED's routes in EVPN address family from"
641 " e1 router."
642 )
643
644 input_dict_rt = {
645 "e1": {
646 "bgp": [
647 {
648 "local_as": "100",
649 "vrf": "RED",
650 "address_family": {
651 "l2vpn": {
652 "evpn": {"route-target": {"export": [{"value": "500:500"}]}}
653 }
654 },
655 }
656 ]
657 }
658 }
659
660 result = create_router_bgp(tgen, topo, input_dict_rt)
661 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
662
663 step(
664 "Verify on dcg-1 and dcg-2, EVPN route for 10.1.1.1/32"
665 " and 10::1/128 have RT value as 500:500."
666 )
667
668 for dut in ["d1", "d2"]:
669 input_routes = {key: topo["routers"][key] for key in ["r1"]}
670 result = verify_attributes_for_evpn_routes(
671 tgen, topo, dut, input_routes, rt=["100:100", "500:500"]
672 )
673 assert result is True, "Testcase {} on {} :Failed \n Error: {}".format(
674 tc_name, dut, result
675 )
676
677 step(
678 "Import RT value 100:100 and 500:500 in vrf BLUE manually on"
679 " peer router DCG-1 and DCG-2."
680 )
681
682 input_dict_rt = {
683 "d1": {
684 "bgp": [
685 {
686 "local_as": "100",
687 "vrf": "BLUE",
688 "address_family": {
689 "l2vpn": {
690 "evpn": {
691 "route-target": {
692 "import": [
693 {"value": "100:100"},
694 {"value": "500:500"},
695 ]
696 }
697 }
698 }
699 },
700 }
701 ]
702 },
703 "d2": {
704 "bgp": [
705 {
706 "local_as": "200",
707 "vrf": "BLUE",
708 "address_family": {
709 "l2vpn": {
710 "evpn": {
711 "route-target": {
712 "import": [
713 {"value": "100:100"},
714 {"value": "500:500"},
715 ]
716 }
717 }
718 }
719 },
720 }
721 ]
722 },
723 }
724
725 result = create_router_bgp(tgen, topo, input_dict_rt)
726 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
727
728 step(
729 "EVPN route for 10.1.1.1/32 and 10::1 should be installed "
730 "in vrf BLUE on DCG-1 and DCG-2 and further advertised to "
731 "VNF router."
732 )
733
734 for addr_type in ADDR_TYPES:
735 input_routes = {
736 "r1": {
737 "static_routes": [{"network": [NETWORK1_1[addr_type]], "vrf": "BLUE"}]
738 }
739 }
740 result = verify_rib(tgen, addr_type, "d1", input_routes)
741 assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
742
743 result = verify_rib(tgen, addr_type, "d2", input_routes)
744 assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
745
746 step(
747 "Delete import RT value 500:500 in vrf BLUE manually on "
748 "peer router DCG-1 and DCG-2."
749 )
750
751 input_dict_rt = {
752 "d1": {
753 "bgp": [
754 {
755 "local_as": "100",
756 "vrf": "BLUE",
757 "address_family": {
758 "l2vpn": {
759 "evpn": {
760 "route-target": {
761 "import": [{"value": "500:500", "delete": True}]
762 }
763 }
764 }
765 },
766 }
767 ]
768 },
769 "d2": {
770 "bgp": [
771 {
772 "local_as": "200",
773 "vrf": "BLUE",
774 "address_family": {
775 "l2vpn": {
776 "evpn": {
777 "route-target": {
778 "import": [{"value": "500:500", "delete": True}]
779 }
780 }
781 }
782 },
783 }
784 ]
785 },
786 }
787
788 result = create_router_bgp(tgen, topo, input_dict_rt)
789 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
790
791 for dut in ["d1", "d2"]:
792 input_routes = {key: topo["routers"][key] for key in ["r1"]}
793 result = verify_attributes_for_evpn_routes(
794 tgen, topo, dut, input_routes, rt=["100:100", "500:500"]
795 )
796 assert result is True, "Testcase {} on {} :Failed \n Error: {}".format(
797 tc_name, dut, result
798 )
799
800 step("Delete RT export value 100:100 for vrf RED on Edge-1")
801
802 input_dict_rt = {
803 "e1": {
804 "bgp": [
805 {
806 "local_as": "100",
807 "vrf": "RED",
808 "address_family": {
809 "l2vpn": {
810 "evpn": {
811 "route-target": {
812 "export": [{"value": "100:100", "delete": True}]
813 }
814 }
815 }
816 },
817 }
818 ]
819 }
820 }
821
822 result = create_router_bgp(tgen, topo, input_dict_rt)
823 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
824
825 step(
826 "EVPN route for 10.1.1.1/32 and 10::1 should be withdrawn "
827 "from vrf BLUE on DCG-1,DCG-2 and VNF router."
828 )
829
830 for addr_type in ADDR_TYPES:
831 input_routes = {
832 "r1": {
833 "static_routes": [{"network": [NETWORK1_1[addr_type]], "vrf": "BLUE"}]
834 }
835 }
836 result = verify_rib(tgen, addr_type, "d1", input_routes, expected=False)
837 assert result is not True, (
838 "Testcase {} : Failed \n "
839 "Expected: Routes should not be present in {} RIB \n "
840 "Found: {}".format(tc_name, "d1", result)
841 )
842
843 result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False)
844 assert result is not True, (
845 "Testcase {} : Failed \n "
846 "Expected: Routes should not be present in {} RIB \n "
847 "Found: {}".format(tc_name, "d2", result)
848 )
849
850 step(
851 "Configure RT value as 100:100000010000010000101010 to check "
852 "the boundary value."
853 )
854
855 input_dict_rt = {
856 "e1": {
857 "bgp": [
858 {
859 "local_as": "100",
860 "vrf": "RED",
861 "address_family": {
862 "l2vpn": {
863 "evpn": {
864 "route-target": {
865 "export": [
866 {"value": "100:100000010000010000101010"}
867 ]
868 }
869 }
870 }
871 },
872 }
873 ]
874 }
875 }
876
877 result = create_router_bgp(tgen, topo, input_dict_rt)
878 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
879
880 step(
881 "CLI error: RT value: 100:100000010000010000101010 should not " "be configured"
882 )
883
884 dut = "e1"
885 input_routes = {key: topo["routers"][key] for key in ["r1"]}
886 result = verify_attributes_for_evpn_routes(
887 tgen, topo, dut, input_routes, rt="100:100000010000010000101010", expected=False
888 )
889 assert result is not True, (
890 "Testcase {} : Failed \n "
891 "Expected: RT value out of boundary error in {} \n "
892 "Found: {}".format(tc_name, dut, result)
893 )
894
895 write_test_footer(tc_name)
896
897
898 def test_active_standby_evpn_implementation_p1(request):
899 """
900 In an active/standby EVPN implementation, if active DCG goes down,
901 secondary takes over.
902 """
903
904 tgen = get_topogen()
905 tc_name = request.node.name
906 write_test_header(tc_name)
907 check_router_status(tgen)
908 reset_config_on_routers(tgen)
909 add_default_routes(tgen)
910
911 if tgen.routers_have_failure():
912 pytest.skip(tgen.errors)
913
914 step(
915 "Taken care in base config: Configure BGP neighborship for both "
916 "address families(IPv4 & IPv6) between DCG-1/DCG-2 and VFN routers"
917 "(R3 and R4)."
918 )
919
920 step(
921 "BGP neighborships come up within defined VRFs. Please use below "
922 "command: sh bgp vrf all summary"
923 )
924
925 result = verify_bgp_convergence(tgen, topo, "d1")
926 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
927
928 result = verify_bgp_convergence(tgen, topo, "d2")
929 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
930
931 step(
932 "Advertise prefixes from VNF routers R3 and R4 in associated "
933 "VRFs for both address-families."
934 )
935
936 for addr_type in ADDR_TYPES:
937 input_dict_1 = {
938 "r3": {
939 "static_routes": [
940 {
941 "network": NETWORK1_2[addr_type],
942 "next_hop": NEXT_HOP_IP[addr_type],
943 "vrf": "RED",
944 }
945 ]
946 },
947 "r4": {
948 "static_routes": [
949 {
950 "network": NETWORK1_3[addr_type],
951 "next_hop": NEXT_HOP_IP[addr_type],
952 "vrf": "BLUE",
953 },
954 {
955 "network": NETWORK1_4[addr_type],
956 "next_hop": NEXT_HOP_IP[addr_type],
957 "vrf": "GREEN",
958 },
959 ]
960 },
961 }
962
963 result = create_static_routes(tgen, input_dict_1)
964 assert result is True, "Testcase {} : Failed \n Error: {}".format(
965 tc_name, result
966 )
967
968 step(
969 "Redistribute static in (IPv4 and IPv6) address-family "
970 "on Edge-1 for all VRFs."
971 )
972
973 input_dict_2 = {}
974 for dut in ["r3", "r4"]:
975 temp = {dut: {"bgp": []}}
976 input_dict_2.update(temp)
977
978 if dut == "r3":
979 VRFS = ["RED"]
980 AS_NUM = [3]
981 if dut == "r4":
982 VRFS = ["BLUE", "GREEN"]
983 AS_NUM = [4, 4]
984
985 for vrf, as_num in zip(VRFS, AS_NUM):
986 temp[dut]["bgp"].append(
987 {
988 "local_as": as_num,
989 "vrf": vrf,
990 "address_family": {
991 "ipv4": {
992 "unicast": {"redistribute": [{"redist_type": "static"}]}
993 },
994 "ipv6": {
995 "unicast": {"redistribute": [{"redist_type": "static"}]}
996 },
997 },
998 }
999 )
1000
1001 result = create_router_bgp(tgen, topo, input_dict_2)
1002 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
1003
1004 step("Prefixes are received in respective VRFs on DCG-1/DCG-2.")
1005
1006 for addr_type in ADDR_TYPES:
1007 input_routes = {
1008 "r3": {
1009 "static_routes": [
1010 {
1011 "network": NETWORK1_2[addr_type],
1012 "next_hop": NEXT_HOP_IP[addr_type],
1013 "vrf": "RED",
1014 }
1015 ]
1016 },
1017 "r4": {
1018 "static_routes": [
1019 {
1020 "network": NETWORK1_3[addr_type],
1021 "next_hop": NEXT_HOP_IP[addr_type],
1022 "vrf": "BLUE",
1023 },
1024 {
1025 "network": NETWORK1_4[addr_type],
1026 "next_hop": NEXT_HOP_IP[addr_type],
1027 "vrf": "GREEN",
1028 },
1029 ]
1030 },
1031 }
1032
1033 result = verify_rib(tgen, addr_type, "d1", input_routes)
1034 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1035 tc_name, result
1036 )
1037
1038 result = verify_rib(tgen, addr_type, "d2", input_routes)
1039 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1040 tc_name, result
1041 )
1042
1043 step(
1044 "Taken care in base config: Advertise VRF routes in EVPN "
1045 "address-family from DCG-1 and DCG-2 router."
1046 )
1047
1048 step("Verify on Edge-1 that EVPN routes are installed via next-hop " "as DCG-2.")
1049
1050 for addr_type in ADDR_TYPES:
1051 input_routes = {
1052 "r3": {
1053 "static_routes": [
1054 {
1055 "network": NETWORK1_2[addr_type],
1056 "next_hop": NEXT_HOP_IP[addr_type],
1057 "vrf": "RED",
1058 }
1059 ]
1060 },
1061 "r4": {
1062 "static_routes": [
1063 {
1064 "network": NETWORK1_3[addr_type],
1065 "next_hop": NEXT_HOP_IP[addr_type],
1066 "vrf": "BLUE",
1067 },
1068 {
1069 "network": NETWORK1_4[addr_type],
1070 "next_hop": NEXT_HOP_IP[addr_type],
1071 "vrf": "GREEN",
1072 },
1073 ]
1074 },
1075 }
1076
1077 if addr_type == "ipv4":
1078 result = verify_rib(
1079 tgen, addr_type, "e1", input_routes, next_hop=BRIDGE_INTF2
1080 )
1081 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1082 tc_name, result
1083 )
1084 else:
1085 result = verify_rib(tgen, addr_type, "e1", input_routes)
1086 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1087 tc_name, result
1088 )
1089
1090 step(
1091 "Configure 'next-hop self' on DCG-1 for peer Edge-1 in EVPN " "address-family."
1092 )
1093
1094 input_dict_3 = {
1095 "d1": {
1096 "bgp": [
1097 {
1098 "local_as": "100",
1099 "address_family": {
1100 "l2vpn": {
1101 "evpn": {
1102 "neighbor": {
1103 "e1": {
1104 "ipv4": {"d1-link1": {"next_hop_self": True}}
1105 }
1106 }
1107 }
1108 }
1109 },
1110 }
1111 ]
1112 }
1113 }
1114
1115 result = create_router_bgp(tgen, topo, input_dict_3)
1116 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
1117
1118 logger.info(
1119 "Creating route-map so ipv6 glpbal ip wpuld be preferred " "as next-hop"
1120 )
1121
1122 step(
1123 "Verify on Edge-1 that EVPN routes are now preferred via "
1124 "next-hop as DCG-1(iBGP) due to shortest AS-Path."
1125 )
1126
1127 for addr_type in ADDR_TYPES:
1128
1129 logger.info("Verifying only ipv4 routes")
1130 if addr_type != "ipv4":
1131 continue
1132
1133 input_routes = {
1134 "r3": {
1135 "static_routes": [
1136 {
1137 "network": NETWORK1_2[addr_type],
1138 "next_hop": NEXT_HOP_IP[addr_type],
1139 "vrf": "RED",
1140 }
1141 ]
1142 },
1143 "r4": {
1144 "static_routes": [
1145 {
1146 "network": NETWORK1_3[addr_type],
1147 "next_hop": NEXT_HOP_IP[addr_type],
1148 "vrf": "BLUE",
1149 },
1150 {
1151 "network": NETWORK1_4[addr_type],
1152 "next_hop": NEXT_HOP_IP[addr_type],
1153 "vrf": "GREEN",
1154 },
1155 ]
1156 },
1157 }
1158
1159 next_hop = topo["routers"]["d1"]["links"]["e1-link1"]["ipv4"].split("/")[0]
1160
1161 result = verify_rib(tgen, addr_type, "e1", input_routes, next_hop=next_hop)
1162 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1163 tc_name, result
1164 )
1165
1166 write_test_footer(tc_name)
1167
1168
1169 def test_evpn_routes_from_VNFs_p1(request):
1170 """
1171 EVPN routes are advertised/withdrawn, based on VNFs
1172 advertising/withdrawing IP prefixes.
1173 """
1174
1175 tgen = get_topogen()
1176 tc_name = request.node.name
1177 write_test_header(tc_name)
1178 check_router_status(tgen)
1179 reset_config_on_routers(tgen)
1180 add_default_routes(tgen)
1181
1182 if tgen.routers_have_failure():
1183 pytest.skip(tgen.errors)
1184
1185 step(
1186 "Advertise prefixes from VNF routers R1 and R2 in associated "
1187 "VRFs for both address-family."
1188 )
1189
1190 for addr_type in ADDR_TYPES:
1191 input_dict_1 = {
1192 "r1": {
1193 "static_routes": [
1194 {
1195 "network": NETWORK1_1[addr_type],
1196 "next_hop": NEXT_HOP_IP[addr_type],
1197 "vrf": "RED",
1198 }
1199 ]
1200 },
1201 "r2": {
1202 "static_routes": [
1203 {
1204 "network": NETWORK2_1[addr_type],
1205 "next_hop": NEXT_HOP_IP[addr_type],
1206 "vrf": "BLUE",
1207 },
1208 {
1209 "network": NETWORK3_1[addr_type],
1210 "next_hop": NEXT_HOP_IP[addr_type],
1211 "vrf": "GREEN",
1212 },
1213 ]
1214 },
1215 }
1216
1217 result = create_static_routes(tgen, input_dict_1)
1218 assert result is True, "Testcase {} : Failed \n Error: {}".format(
1219 tc_name, result
1220 )
1221
1222 step(
1223 "Taken care in base config: Advertise VNFs'(R1 and R2) "
1224 "originated routes in EVPN address-family from Edge-1 to "
1225 "DCG-1 and DCG-2 routers."
1226 )
1227 step(
1228 "Taken care in base config: Advertise IPv4 and IPv6 routes "
1229 "from default vrf in EVPN address-family from Edge-1."
1230 )
1231
1232 step(
1233 "Verify on DCG-2 that VNF routes are received in respective "
1234 "VRFs along with auto derived RD/RT values 'show bgp l2vpn evpn'"
1235 )
1236 for dut in ["d1", "d2"]:
1237 input_routes = {key: topo["routers"][key] for key in ["r1"]}
1238 result = verify_evpn_routes(tgen, topo, dut, input_routes)
1239 assert result is True, "Testcase {} on {} :Failed \n Error: {}".format(
1240 tc_name, dut, result
1241 )
1242
1243 input_routes = {key: topo["routers"][key] for key in ["r2"]}
1244 result = verify_evpn_routes(tgen, topo, dut, input_routes)
1245 assert result is True, "Testcase {} on {} :Failed \n Error: {}".format(
1246 tc_name, dut, result
1247 )
1248
1249 step(
1250 "Verify on R3 and R4 that DCG-2 further advertises all EVPN "
1251 "routes to corresponding VRFs."
1252 )
1253 for addr_type in ADDR_TYPES:
1254 input_routes = {key: topo["routers"][key] for key in ["r1"]}
1255 result = verify_rib(tgen, addr_type, "r3", input_routes)
1256 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1257 tc_name, result
1258 )
1259
1260 for addr_type in ADDR_TYPES:
1261 input_routes = {key: topo["routers"][key] for key in ["r2"]}
1262 result = verify_rib(tgen, addr_type, "r4", input_routes)
1263 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1264 tc_name, result
1265 )
1266
1267 step(
1268 "Verify that DCG-2 receives EVPN routes associated to default "
1269 "VRF and install in default IP routing table as well."
1270 )
1271 for addr_type in ADDR_TYPES:
1272 input_routes = {key: topo["routers"][key] for key in ["r1"]}
1273 result = verify_rib(tgen, addr_type, "d2", input_routes)
1274 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1275 tc_name, result
1276 )
1277
1278 for addr_type in ADDR_TYPES:
1279 input_routes = {key: topo["routers"][key] for key in ["r2"]}
1280 result = verify_rib(tgen, addr_type, "d2", input_routes)
1281 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1282 tc_name, result
1283 )
1284
1285 step("Withdraw the IP prefixes from VFN(R1).")
1286 dut = "r1"
1287 input_dict_2 = {}
1288 static_routes = topo["routers"][dut]["static_routes"]
1289 for static_route in static_routes:
1290 static_route["delete"] = True
1291 temp = {dut: {"static_routes": [static_route]}}
1292 input_dict_2.update(temp)
1293
1294 result = create_static_routes(tgen, input_dict_2)
1295 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1296 tc_name, result
1297 )
1298
1299 step(
1300 "Verify that DCG-2 removes EVPN routes corresponding to vrf RED and "
1301 "send an withdraw to VNF(R3) as well."
1302 )
1303 for addr_type in ADDR_TYPES:
1304 input_routes = {key: topo["routers"][key] for key in ["r1"]}
1305 result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False)
1306 assert result is not True, (
1307 "Testcase {} : Failed \n "
1308 "Expected: Routes should not be present in {} RIB \n "
1309 "Found: {}".format(tc_name, "d2", result)
1310 )
1311
1312 for addr_type in ADDR_TYPES:
1313 input_routes = {key: topo["routers"][key] for key in ["r1"]}
1314 result = verify_rib(tgen, addr_type, "r3", input_routes, expected=False)
1315 assert result is not True, (
1316 "Testcase {} : Failed \n "
1317 "Expected: Routes should not be present in {} RIB \n "
1318 "Found: {}".format(tc_name, "r3", result)
1319 )
1320
1321 step("Re-advertise IP prefixes from VFN(R1).")
1322 step(
1323 "Advertise prefixes from VNF routers R1 and R2 in associated "
1324 "VRFs for both address-family."
1325 )
1326
1327 for addr_type in ADDR_TYPES:
1328 input_dict_1 = {
1329 "r1": {
1330 "static_routes": [
1331 {
1332 "network": NETWORK1_1[addr_type],
1333 "next_hop": NEXT_HOP_IP[addr_type],
1334 "vrf": "RED",
1335 }
1336 ]
1337 },
1338 "r2": {
1339 "static_routes": [
1340 {
1341 "network": NETWORK2_1[addr_type],
1342 "next_hop": NEXT_HOP_IP[addr_type],
1343 "vrf": "BLUE",
1344 },
1345 {
1346 "network": NETWORK3_1[addr_type],
1347 "next_hop": NEXT_HOP_IP[addr_type],
1348 "vrf": "GREEN",
1349 },
1350 ]
1351 },
1352 }
1353
1354 result = create_static_routes(tgen, input_dict_1)
1355 assert result is True, "Testcase {} : Failed \n Error: {}".format(
1356 tc_name, result
1357 )
1358
1359 step(
1360 "Verify that DCG-2 receives EVPN routes corresponding to vrf RED "
1361 "again and send an update to VNF(R3) as well."
1362 )
1363 for addr_type in ADDR_TYPES:
1364 input_routes = {key: topo["routers"][key] for key in ["r1"]}
1365 result = verify_rib(tgen, addr_type, "d2", input_routes)
1366 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1367 tc_name, result
1368 )
1369
1370 for addr_type in ADDR_TYPES:
1371 input_routes = {key: topo["routers"][key] for key in ["r1"]}
1372 result = verify_rib(tgen, addr_type, "r3", input_routes)
1373 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1374 tc_name, result
1375 )
1376
1377 step("Delete vrf BLUE from router Edge-1")
1378 input_dict_3 = {"e1": {"vrfs": [{"name": "BLUE", "id": "2", "delete": True}]}}
1379
1380 result = create_vrf_cfg(tgen, input_dict_3)
1381 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
1382
1383 step(
1384 "Verify that DCG-2 removes EVPN routes corresponding to "
1385 "vrf BLUE and send an withdraw to VNF(R4) as well."
1386 )
1387 for addr_type in ADDR_TYPES:
1388 input_routes = {
1389 "r2": {"static_routes": [{"network": NETWORK2_1[addr_type], "vrf": "BLUE"}]}
1390 }
1391
1392 result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False)
1393 assert result is not True, (
1394 "Testcase {} : Failed \n "
1395 "Expected: Routes should not be present in {} RIB \n "
1396 "Found: {}".format(tc_name, "d2", result)
1397 )
1398
1399 result = verify_rib(tgen, addr_type, "r4", input_routes, expected=False)
1400 assert result is not True, (
1401 "Testcase {} : Failed \n "
1402 "Expected: Routes should not be present in {} RIB \n "
1403 "Found: {}".format(tc_name, "r4", result)
1404 )
1405
1406 step("Add vrf BLUE on router Edge-1 again.")
1407 interface = topo["routers"]["e1"]["links"]["r2-link1"]["interface"]
1408 input_dict_3 = {
1409 "e1": {
1410 "links": {
1411 "r2-link1": {
1412 "interface": interface,
1413 "ipv4": "auto",
1414 "ipv6": "auto",
1415 "vrf": "BLUE",
1416 }
1417 },
1418 "vrfs": [{"name": "BLUE", "id": "2"}],
1419 }
1420 }
1421 result = create_vrf_cfg(tgen, input_dict_3)
1422 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
1423
1424 logger.info(
1425 "After deleting VRFs ipv6 addresses wil be deleted "
1426 "from kernel Adding back ipv6 addresses"
1427 )
1428 dut = "e1"
1429 vrfs = ["BLUE"]
1430
1431 for vrf in vrfs:
1432 for c_link, c_data in topo["routers"][dut]["links"].items():
1433 if "vrf" in c_data:
1434 if c_data["vrf"] != vrf:
1435 continue
1436
1437 intf_name = c_data["interface"]
1438 intf_ipv6 = c_data["ipv6"]
1439
1440 create_interface_in_kernel(
1441 tgen, dut, intf_name, intf_ipv6, vrf, create=False
1442 )
1443
1444 result = verify_bgp_convergence(tgen, topo, dut)
1445 assert result is True, "Failed to converge on {}".format(dut)
1446
1447 step(
1448 "Verify that DCG-2 receives EVPN routes corresponding to "
1449 "vrf BLUE again and send an update to VNF(R4) as well."
1450 )
1451 for addr_type in ADDR_TYPES:
1452 input_routes = {
1453 "r2": {"static_routes": [{"network": NETWORK2_1[addr_type], "vrf": "BLUE"}]}
1454 }
1455
1456 result = verify_rib(tgen, addr_type, "d2", input_routes)
1457 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1458 tc_name, result
1459 )
1460
1461 result = verify_rib(tgen, addr_type, "r4", input_routes)
1462 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1463 tc_name, result
1464 )
1465
1466 step("Withdraw IPv6 address-family in EVPN advertisements for " "VRF GREEN")
1467 addr_type = "ipv6"
1468 input_dict_4 = {
1469 "e1": {
1470 "bgp": [
1471 {
1472 "local_as": "100",
1473 "vrf": "GREEN",
1474 "address_family": {
1475 "l2vpn": {
1476 "evpn": {
1477 "advertise": {addr_type: {"unicast": {"delete": True}}}
1478 }
1479 }
1480 },
1481 }
1482 ]
1483 }
1484 }
1485
1486 result = create_router_bgp(tgen, topo, input_dict_4)
1487 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
1488
1489 step(
1490 "Verify that EVPN routes (IPv6)associated with vrf GREEN are "
1491 "withdrawn from DCG-2 and VNF R4."
1492 )
1493 input_routes = {
1494 "r2": {"static_routes": [{"network": NETWORK3_1[addr_type], "vrf": "GREEN"}]}
1495 }
1496
1497 result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False)
1498 assert result is not True, (
1499 "Testcase {} : Failed \n "
1500 "Expected: Routes should not be present in {} RIB \n "
1501 "Found: {}".format(tc_name, "d2", result)
1502 )
1503
1504 result = verify_rib(tgen, addr_type, "r4", input_routes, expected=False)
1505 assert result is not True, (
1506 "Testcase {} : Failed \n "
1507 "Expected: Routes should not be present in {} RIB \n "
1508 "Found: {}".format(tc_name, "r4", result)
1509 )
1510
1511 step("Advertise IPv6 address-family in EVPN advertisements " "for VRF GREEN.")
1512 addr_type = "ipv6"
1513 input_dict_4 = {
1514 "e1": {
1515 "bgp": [
1516 {
1517 "local_as": "100",
1518 "vrf": "GREEN",
1519 "address_family": {
1520 "l2vpn": {"evpn": {"advertise": {addr_type: {"unicast": {}}}}}
1521 },
1522 }
1523 ]
1524 }
1525 }
1526
1527 result = create_router_bgp(tgen, topo, input_dict_4)
1528 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
1529
1530 for addr_type in ADDR_TYPES:
1531 input_routes = {
1532 "r2": {
1533 "static_routes": [{"network": NETWORK3_1[addr_type], "vrf": "GREEN"}]
1534 }
1535 }
1536
1537 result = verify_rib(tgen, addr_type, "d2", input_routes)
1538 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1539 tc_name, result
1540 )
1541
1542 result = verify_rib(tgen, addr_type, "r4", input_routes)
1543 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1544 tc_name, result
1545 )
1546
1547 write_test_footer(tc_name)
1548
1549
1550 @pytest.mark.parametrize(
1551 "attribute", [{"route-type": "prefix"}, {"vni": VNI_1}, {"rt": "300:300"}]
1552 )
1553 def test_route_map_operations_for_evpn_address_family_p1(request, attribute):
1554 """
1555 Route-map operations for EVPN address family.
1556 """
1557
1558 tgen = get_topogen()
1559 tc_name = request.node.name
1560 write_test_header(tc_name)
1561 check_router_status(tgen)
1562 reset_config_on_routers(tgen)
1563 add_default_routes(tgen)
1564
1565 step(
1566 "Advertise prefixes from VNF routers R1 and R2 in associated "
1567 "VRFs for both address-family."
1568 )
1569
1570 for addr_type in ADDR_TYPES:
1571 input_dict_1 = {
1572 "r1": {
1573 "static_routes": [
1574 {
1575 "network": NETWORK1_1[addr_type],
1576 "next_hop": NEXT_HOP_IP[addr_type],
1577 "vrf": "RED",
1578 }
1579 ]
1580 },
1581 "r2": {
1582 "static_routes": [
1583 {
1584 "network": NETWORK2_1[addr_type],
1585 "next_hop": NEXT_HOP_IP[addr_type],
1586 "vrf": "BLUE",
1587 },
1588 {
1589 "network": NETWORK3_1[addr_type],
1590 "next_hop": NEXT_HOP_IP[addr_type],
1591 "vrf": "GREEN",
1592 },
1593 ]
1594 },
1595 }
1596
1597 result = create_static_routes(tgen, input_dict_1)
1598 assert result is True, "Testcase {} : Failed \n Error: {}".format(
1599 tc_name, result
1600 )
1601
1602 if tgen.routers_have_failure():
1603 pytest.skip(tgen.errors)
1604
1605 step(
1606 "Advertise VRF routes in EVPN address family from Edge-1 router."
1607 " Configure a route-map on e1 to filter EVPN routes based on"
1608 " below keywords: route-type: prefix"
1609 )
1610
1611 for key, value in attribute.items():
1612 if key == "rt":
1613 logger.info("Creating extcommunity using raw_config")
1614 raw_config = {
1615 "d2": {
1616 "raw_config": [
1617 "bgp extcommunity-list standard ECOMM300 permit {} {}".format(
1618 key, value
1619 )
1620 ]
1621 }
1622 }
1623 result = apply_raw_config(tgen, raw_config)
1624 assert result is True, "Testcase {} : Failed Error: {}".format(
1625 tc_name, result
1626 )
1627
1628 input_dict_1 = {
1629 "e1": {
1630 "route_maps": {
1631 "rmap_route_type": [
1632 {"action": "permit", "set": {"extcommunity": {key: value}}}
1633 ]
1634 }
1635 },
1636 "d2": {
1637 "route_maps": {
1638 "rmap_route_type": [
1639 {"action": "permit", "match": {"extcommunity": "ECOMM300"}}
1640 ]
1641 }
1642 },
1643 }
1644
1645 else:
1646 input_dict_1 = {
1647 "e1": {
1648 "route_maps": {
1649 "rmap_route_type": [
1650 {"action": "permit", "match": {"evpn": {key: value}}}
1651 ]
1652 }
1653 },
1654 "d2": {
1655 "route_maps": {
1656 "rmap_route_type": [
1657 {"action": "permit", "match": {"evpn": {key: value}}}
1658 ]
1659 }
1660 },
1661 }
1662 result = create_route_maps(tgen, input_dict_1)
1663 assert result is True, "Testcase {} : Failed \n Error: {}".format(
1664 tc_name, result
1665 )
1666
1667 input_dict_2 = {
1668 "e1": {
1669 "bgp": [
1670 {
1671 "local_as": "100",
1672 "address_family": {
1673 "l2vpn": {
1674 "evpn": {
1675 "neighbor": {
1676 "d2": {
1677 "ipv4": {
1678 "e1-link1": {
1679 "route_maps": [
1680 {
1681 "name": "rmap_route_type",
1682 "direction": "out",
1683 }
1684 ]
1685 }
1686 }
1687 }
1688 }
1689 }
1690 }
1691 },
1692 }
1693 ]
1694 },
1695 "d2": {
1696 "bgp": [
1697 {
1698 "local_as": "200",
1699 "address_family": {
1700 "l2vpn": {
1701 "evpn": {
1702 "neighbor": {
1703 "e1": {
1704 "ipv4": {
1705 "d2-link1": {
1706 "route_maps": [
1707 {
1708 "name": "rmap_route_type",
1709 "direction": "in",
1710 }
1711 ]
1712 }
1713 }
1714 }
1715 }
1716 }
1717 }
1718 },
1719 }
1720 ]
1721 },
1722 }
1723
1724 result = create_router_bgp(tgen, topo, input_dict_2)
1725 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
1726
1727 step(
1728 "Verify on router DCG-2 that EVPN routes corresponding to all "
1729 "VRFs are received. As all EVPN routes are type-5 only."
1730 )
1731
1732 input_routes = {key: topo["routers"][key] for key in ["r1"]}
1733 result = verify_evpn_routes(tgen, topo, "d2", input_routes)
1734 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
1735
1736 input_routes = {key: topo["routers"][key] for key in ["r2"]}
1737 result = verify_evpn_routes(tgen, topo, "d2", input_routes)
1738 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
1739
1740 write_test_footer(tc_name)
1741
1742
1743 def test_evpn_address_family_with_graceful_restart_p0(request):
1744 """
1745 Verify Graceful-restart function for EVPN address-family.
1746 """
1747
1748 tgen = get_topogen()
1749 tc_name = request.node.name
1750 write_test_header(tc_name)
1751 check_router_status(tgen)
1752 reset_config_on_routers(tgen)
1753 add_default_routes(tgen)
1754
1755 if tgen.routers_have_failure():
1756 pytest.skip(tgen.errors)
1757
1758 for addr_type in ADDR_TYPES:
1759 input_dict_1 = {
1760 "r3": {
1761 "static_routes": [
1762 {
1763 "network": NETWORK1_2[addr_type],
1764 "next_hop": NEXT_HOP_IP[addr_type],
1765 "vrf": "RED",
1766 }
1767 ]
1768 },
1769 "r4": {
1770 "static_routes": [
1771 {
1772 "network": NETWORK1_3[addr_type],
1773 "next_hop": NEXT_HOP_IP[addr_type],
1774 "vrf": "BLUE",
1775 },
1776 {
1777 "network": NETWORK1_4[addr_type],
1778 "next_hop": NEXT_HOP_IP[addr_type],
1779 "vrf": "GREEN",
1780 },
1781 ]
1782 },
1783 }
1784
1785 result = create_static_routes(tgen, input_dict_1)
1786 assert result is True, "Testcase {} : Failed \n Error: {}".format(
1787 tc_name, result
1788 )
1789
1790 step(
1791 "Redistribute static in (IPv4 and IPv6) address-family "
1792 "on Edge-1 for all VRFs."
1793 )
1794
1795 input_dict_2 = {}
1796 for dut in ["r3", "r4"]:
1797 temp = {dut: {"bgp": []}}
1798 input_dict_2.update(temp)
1799
1800 if dut == "r3":
1801 VRFS = ["RED"]
1802 AS_NUM = [3]
1803 if dut == "r4":
1804 VRFS = ["BLUE", "GREEN"]
1805 AS_NUM = [4, 4]
1806
1807 for vrf, as_num in zip(VRFS, AS_NUM):
1808 temp[dut]["bgp"].append(
1809 {
1810 "local_as": as_num,
1811 "vrf": vrf,
1812 "address_family": {
1813 "ipv4": {
1814 "unicast": {"redistribute": [{"redist_type": "static"}]}
1815 },
1816 "ipv6": {
1817 "unicast": {"redistribute": [{"redist_type": "static"}]}
1818 },
1819 },
1820 }
1821 )
1822
1823 result = create_router_bgp(tgen, topo, input_dict_2)
1824 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
1825
1826 step(
1827 "Verify on router Edge-1 that EVPN routes corresponding to "
1828 "all VRFs are received from both routers DCG-1 and DCG-2"
1829 )
1830
1831 for addr_type in ADDR_TYPES:
1832 input_routes = {
1833 "r3": {
1834 "static_routes": [
1835 {
1836 "network": NETWORK1_2[addr_type],
1837 "next_hop": NEXT_HOP_IP[addr_type],
1838 "vrf": "RED",
1839 }
1840 ]
1841 },
1842 "r4": {
1843 "static_routes": [
1844 {
1845 "network": NETWORK1_3[addr_type],
1846 "next_hop": NEXT_HOP_IP[addr_type],
1847 "vrf": "BLUE",
1848 },
1849 {
1850 "network": NETWORK1_4[addr_type],
1851 "next_hop": NEXT_HOP_IP[addr_type],
1852 "vrf": "GREEN",
1853 },
1854 ]
1855 },
1856 }
1857
1858 result = verify_rib(tgen, addr_type, "e1", input_routes)
1859 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1860 tc_name, result
1861 )
1862
1863 step(
1864 "Configure DCG-2 as GR restarting node for EVPN session between"
1865 " DCG-2 and EDGE-1, following by a session reset using 'clear bgp *'"
1866 " command."
1867 )
1868
1869 input_dict_gr = {
1870 "d2": {
1871 "bgp": [
1872 {
1873 "local_as": "200",
1874 "graceful-restart": {
1875 "graceful-restart": True,
1876 },
1877 }
1878 ]
1879 }
1880 }
1881
1882 result = create_router_bgp(tgen, topo, input_dict_gr)
1883 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
1884
1885 step(
1886 "Verify that DCG-2 changes it's role to GR-restarting router "
1887 "and EDGE-1 becomes the GR-helper."
1888 )
1889
1890 step("Kill BGPd daemon on DCG-2.")
1891 kill_router_daemons(tgen, "d2", ["bgpd"])
1892
1893 step(
1894 "Verify that EDGE-1 keep stale entries for EVPN RT-5 routes "
1895 "received from DCG-2 before the restart."
1896 )
1897
1898 for addr_type in ADDR_TYPES:
1899 input_routes = {
1900 "r4": {
1901 "static_routes": [
1902 {
1903 "network": NETWORK1_3[addr_type],
1904 "next_hop": NEXT_HOP_IP[addr_type],
1905 "vrf": "BLUE",
1906 },
1907 {
1908 "network": NETWORK1_4[addr_type],
1909 "next_hop": NEXT_HOP_IP[addr_type],
1910 "vrf": "GREEN",
1911 },
1912 ]
1913 }
1914 }
1915 result = verify_evpn_routes(tgen, topo, "e1", input_routes)
1916 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1917 tc_name, result
1918 )
1919
1920 step(
1921 "Verify that DCG-2 keeps BGP routes in Zebra until BGPd "
1922 "comes up or end of 'rib-stale-time'"
1923 )
1924
1925 step("Start BGPd daemon on DCG-2.")
1926 start_router_daemons(tgen, "d2", ["bgpd"])
1927
1928 step("Verify that EDGE-1 removed all the stale entries.")
1929 for addr_type in ADDR_TYPES:
1930 input_routes = {
1931 "r4": {
1932 "static_routes": [
1933 {
1934 "network": NETWORK1_3[addr_type],
1935 "next_hop": NEXT_HOP_IP[addr_type],
1936 "vrf": "BLUE",
1937 },
1938 {
1939 "network": NETWORK1_4[addr_type],
1940 "next_hop": NEXT_HOP_IP[addr_type],
1941 "vrf": "GREEN",
1942 },
1943 ]
1944 }
1945 }
1946 result = verify_evpn_routes(tgen, topo, "e1", input_routes)
1947 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1948 tc_name, result
1949 )
1950
1951 step(
1952 "Verify that DCG-2 refresh zebra with EVPN routes. "
1953 "(no significance of 'rib-stale-time'"
1954 )
1955
1956 for addr_type in ADDR_TYPES:
1957 input_routes = {
1958 "r4": {
1959 "static_routes": [
1960 {
1961 "network": NETWORK1_3[addr_type],
1962 "next_hop": NEXT_HOP_IP[addr_type],
1963 "vrf": "BLUE",
1964 },
1965 {
1966 "network": NETWORK1_4[addr_type],
1967 "next_hop": NEXT_HOP_IP[addr_type],
1968 "vrf": "GREEN",
1969 },
1970 ]
1971 }
1972 }
1973 result = verify_rib(tgen, addr_type, "d2", input_routes)
1974 assert result is True, "Testcase {} :Failed \n Error: {}".format(
1975 tc_name, result
1976 )
1977
1978 write_test_footer(tc_name)
1979
1980
1981 @pytest.mark.parametrize("attribute", ["locPrf", "weight", "path"])
1982 def test_bgp_attributes_for_evpn_address_family_p1(request, attribute):
1983 """
1984 BGP attributes for EVPN address-family.
1985 """
1986
1987 tgen = get_topogen()
1988 tc_name = request.node.name
1989 write_test_header(tc_name)
1990 check_router_status(tgen)
1991 reset_config_on_routers(tgen)
1992 add_default_routes(tgen)
1993
1994 if tgen.routers_have_failure():
1995 pytest.skip(tgen.errors)
1996
1997 step(
1998 "Advertise prefixes from VNF routers R1 and R2 in associated "
1999 "VRFs for both address-family."
2000 )
2001
2002 for addr_type in ADDR_TYPES:
2003 input_dict_1 = {
2004 "r1": {
2005 "static_routes": [
2006 {
2007 "network": NETWORK1_1[addr_type],
2008 "next_hop": NEXT_HOP_IP[addr_type],
2009 "vrf": "RED",
2010 }
2011 ]
2012 },
2013 "r2": {
2014 "static_routes": [
2015 {
2016 "network": NETWORK2_1[addr_type],
2017 "next_hop": NEXT_HOP_IP[addr_type],
2018 "vrf": "BLUE",
2019 },
2020 {
2021 "network": NETWORK3_1[addr_type],
2022 "next_hop": NEXT_HOP_IP[addr_type],
2023 "vrf": "GREEN",
2024 },
2025 ]
2026 },
2027 }
2028
2029 result = create_static_routes(tgen, input_dict_1)
2030 assert result is True, "Testcase {} : Failed \n Error: {}".format(
2031 tc_name, result
2032 )
2033
2034 topo_local = deepcopy(topo)
2035
2036 logger.info("Modifying topology b/w e1 and d1 from iBGP to eBGP")
2037 step("Delete BGP config for vrf RED.")
2038
2039 if attribute == "locPrf":
2040 input_dict_vni = {
2041 "d1": {
2042 "vrfs": [
2043 {"name": "RED", "no_vni": VNI_1},
2044 {"name": "BLUE", "no_vni": VNI_2},
2045 {"name": "GREEN", "no_vni": VNI_3},
2046 ]
2047 }
2048 }
2049 result = create_vrf_cfg(tgen, topo, input_dict=input_dict_vni)
2050 assert result is True, "Testcase {} :Failed \n Error: {}".format(
2051 tc_name, result
2052 )
2053
2054 input_dict_2 = {}
2055 for dut in ["d1"]:
2056 temp = {dut: {"bgp": []}}
2057 input_dict_2.update(temp)
2058
2059 INDEX = [0, 1, 2, 3]
2060 VRFS = ["RED", "BLUE", "GREEN", None]
2061 AS_NUM = [100, 100, 100, 100]
2062
2063 for index, vrf, as_num in zip(INDEX, VRFS, AS_NUM):
2064 topo_local["routers"][dut]["bgp"][index]["local_as"] = 200
2065 if vrf:
2066 temp[dut]["bgp"].append(
2067 {"local_as": as_num, "vrf": vrf, "delete": True}
2068 )
2069 else:
2070 temp[dut]["bgp"].append({"local_as": as_num, "delete": True})
2071
2072 result = create_router_bgp(tgen, topo, input_dict_2)
2073 assert result is True, "Testcase {} on d1 :Failed \n Error: {}".format(
2074 tc_name, result
2075 )
2076
2077 result = create_router_bgp(tgen, topo_local["routers"])
2078 assert result is True, "Testcase {} :Failed \n Error: {}".format(
2079 tc_name, result
2080 )
2081
2082 step("Advertise VRF routes in EVPN address-family from DCG-1 " "and DCG-2 routers.")
2083
2084 for addr_type in ADDR_TYPES:
2085 input_dict_1 = {
2086 "r3": {
2087 "static_routes": [
2088 {
2089 "network": NETWORK1_2[addr_type],
2090 "next_hop": NEXT_HOP_IP[addr_type],
2091 "vrf": "RED",
2092 }
2093 ]
2094 },
2095 "r4": {
2096 "static_routes": [
2097 {
2098 "network": NETWORK1_3[addr_type],
2099 "next_hop": NEXT_HOP_IP[addr_type],
2100 "vrf": "BLUE",
2101 },
2102 {
2103 "network": NETWORK1_4[addr_type],
2104 "next_hop": NEXT_HOP_IP[addr_type],
2105 "vrf": "GREEN",
2106 },
2107 ]
2108 },
2109 }
2110
2111 result = create_static_routes(tgen, input_dict_1)
2112 assert result is True, "Testcase {} : Failed \n Error: {}".format(
2113 tc_name, result
2114 )
2115
2116 step(
2117 "Redistribute static in (IPv4 and IPv6) address-family "
2118 "on Edge-1 for all VRFs."
2119 )
2120
2121 input_dict_2 = {}
2122 for dut in ["r3", "r4"]:
2123 temp = {dut: {"bgp": []}}
2124 input_dict_2.update(temp)
2125
2126 if dut == "r3":
2127 VRFS = ["RED"]
2128 AS_NUM = [3]
2129 if dut == "r4":
2130 VRFS = ["BLUE", "GREEN"]
2131 AS_NUM = [4, 4]
2132
2133 for vrf, as_num in zip(VRFS, AS_NUM):
2134 temp[dut]["bgp"].append(
2135 {
2136 "local_as": as_num,
2137 "vrf": vrf,
2138 "address_family": {
2139 "ipv4": {
2140 "unicast": {"redistribute": [{"redist_type": "static"}]}
2141 },
2142 "ipv6": {
2143 "unicast": {"redistribute": [{"redist_type": "static"}]}
2144 },
2145 },
2146 }
2147 )
2148
2149 result = create_router_bgp(tgen, topo, input_dict_2)
2150 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
2151
2152 step(
2153 "Verify on router Edge-1 that EVPN routes corresponding to "
2154 "all VRFs are received from both routers DCG-1 and DCG-2"
2155 )
2156
2157 for addr_type in ADDR_TYPES:
2158 input_routes = {
2159 "r3": {
2160 "static_routes": [
2161 {
2162 "network": NETWORK1_2[addr_type],
2163 "next_hop": NEXT_HOP_IP[addr_type],
2164 "vrf": "RED",
2165 }
2166 ]
2167 },
2168 "r4": {
2169 "static_routes": [
2170 {
2171 "network": NETWORK1_3[addr_type],
2172 "next_hop": NEXT_HOP_IP[addr_type],
2173 "vrf": "BLUE",
2174 },
2175 {
2176 "network": NETWORK1_4[addr_type],
2177 "next_hop": NEXT_HOP_IP[addr_type],
2178 "vrf": "GREEN",
2179 },
2180 ]
2181 },
2182 }
2183
2184 result = verify_rib(tgen, addr_type, "e1", input_routes)
2185 assert result is True, "Testcase {} :Failed \n Error: {}".format(
2186 tc_name, result
2187 )
2188
2189 step(
2190 "Configure a route-map on Edge-1 to modify below BGP attributes "
2191 "for EVPN address-family:"
2192 )
2193
2194 if attribute == "path":
2195 input_dict_1 = {
2196 "e1": {
2197 "route_maps": {
2198 "rmap_d1": [
2199 {
2200 "action": "permit",
2201 "set": {
2202 attribute: {
2203 "as_num": "123 231 321",
2204 "as_action": "prepend",
2205 }
2206 },
2207 }
2208 ],
2209 "rmap_d2": [
2210 {
2211 "action": "permit",
2212 "set": {
2213 attribute: {"as_num": "121", "as_action": "prepend"}
2214 },
2215 }
2216 ],
2217 }
2218 }
2219 }
2220 else:
2221 input_dict_1 = {
2222 "e1": {
2223 "route_maps": {
2224 "rmap_d1": [{"action": "permit", "set": {attribute: 120}}],
2225 "rmap_d2": [{"action": "permit", "set": {attribute: 150}}],
2226 }
2227 }
2228 }
2229 result = create_route_maps(tgen, input_dict_1)
2230 assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
2231
2232 input_dict_2 = {
2233 "e1": {
2234 "bgp": [
2235 {
2236 "local_as": "100",
2237 "address_family": {
2238 "l2vpn": {
2239 "evpn": {
2240 "neighbor": {
2241 "d1": {
2242 "ipv4": {
2243 "e1-link1": {
2244 "route_maps": [
2245 {
2246 "name": "rmap_d1",
2247 "direction": "in",
2248 }
2249 ]
2250 }
2251 }
2252 },
2253 "d2": {
2254 "ipv4": {
2255 "e1-link1": {
2256 "route_maps": [
2257 {
2258 "name": "rmap_d2",
2259 "direction": "in",
2260 }
2261 ]
2262 }
2263 }
2264 },
2265 }
2266 }
2267 }
2268 },
2269 }
2270 ]
2271 }
2272 }
2273
2274 result = create_router_bgp(tgen, topo, input_dict_2)
2275 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
2276
2277 step(
2278 "Verify on router Edge-1 that EVPN routes are preferred via"
2279 " DCG-1 or DCG-2 based on best path selection criteria "
2280 "(according to the configured BGP attribute values in route-map)."
2281 )
2282
2283 for addr_type in ADDR_TYPES:
2284 input_routes = {
2285 "r3": {
2286 "static_routes": [
2287 {
2288 "network": NETWORK1_2[addr_type],
2289 "next_hop": NEXT_HOP_IP[addr_type],
2290 "vrf": "RED",
2291 }
2292 ]
2293 },
2294 "r4": {
2295 "static_routes": [
2296 {
2297 "network": NETWORK1_3[addr_type],
2298 "next_hop": NEXT_HOP_IP[addr_type],
2299 "vrf": "BLUE",
2300 },
2301 {
2302 "network": NETWORK1_4[addr_type],
2303 "next_hop": NEXT_HOP_IP[addr_type],
2304 "vrf": "GREEN",
2305 },
2306 ]
2307 },
2308 }
2309
2310 result = verify_best_path_as_per_bgp_attribute(
2311 tgen, addr_type, "e1", input_routes, attribute
2312 )
2313 assert result is True, "Testcase {} : Failed \n Error: {}".format(
2314 tc_name, result
2315 )
2316
2317 write_test_footer(tc_name)
2318
2319
2320 if __name__ == "__main__":
2321 args = ["-s"] + sys.argv[1:]
2322 sys.exit(pytest.main(args))