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