2 # SPDX-License-Identifier: ISC
5 # Copyright (c) 2020 by VMware, Inc. ("VMware")
6 # Used Copyright (c) 2018 by Network Device Education Foundation,
7 # Inc. ("NetDEF") in this file.
11 Following tests are covered to test multicast pim sm:
14 - Create topology (setup module)
17 Following tests are covered:
18 1. Verify mroutes when transit router present between RP and Source DR
26 from time
import sleep
29 # Save the Current Working Directory to find configuration files.
30 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
31 sys
.path
.append(os
.path
.join(CWD
, "../"))
32 sys
.path
.append(os
.path
.join(CWD
, "../lib/"))
34 # Required to instantiate the topology builder class.
36 # pylint: disable=C0413
37 # Import topogen and topotest helpers
38 from lib
.topogen
import Topogen
, get_topogen
40 from lib
.common_config
import (
45 reset_config_on_routers
,
47 add_interfaces_to_vlan
,
50 required_linux_kernel_version
,
57 clear_pim_interface_traffic
,
60 verify_multicast_traffic
,
63 from lib
.topolog
import logger
64 from lib
.topojson
import build_config_from_json
69 pytestmark
= [pytest
.mark
.pimd
]
73 Descripton: Configuring OSPF on r1/r2/r4/r5/r6 for RP reachablility, We have r6 as a transit router between
75 IPs are assigned automatically to routers, start IP and subnet is defined in respective JSON file
77 "link_ip_start": {"ipv4": "10.0.0.0", "v4mask": 24},
80 10.0.3.2/24| 10.0.0.2/24
87 ------------ r6 ----------
88 | 10.0.1.2/24 10.0.2.2/24 |
89 10.0.1.1/24 | | 10.0.2.1/24
90 r1 ----------- s1 ---------- r2
91 10.0.5.2/24 | 10.0.5.3/24
99 i1, i2 - FRR running iperf to send IGMP
101 r1, r2, r4, r5, r6 - FRR ruter
107 GROUP_RANGE
= "225.0.0.0/8"
108 IGMP_JOIN
= "225.1.1.1"
109 VLAN_INTF_ADRESS_1
= "10.0.8.3/24"
110 SAME_VLAN_IP_1
= {"ip": "10.1.1.1", "subnet": "255.255.255.0", "cidr": "24"}
111 SAME_VLAN_IP_2
= {"ip": "10.1.1.2", "subnet": "255.255.255.0", "cidr": "24"}
112 SAME_VLAN_IP_3
= {"ip": "10.1.1.3", "subnet": "255.255.255.0", "cidr": "24"}
113 SAME_VLAN_IP_4
= {"ip": "10.1.1.4", "subnet": "255.255.255.0", "cidr": "24"}
121 IGMP_JOIN_RANGE_1
= ["225.1.1.1", "225.1.1.2", "225.1.1.3", "225.1.1.4", "225.1.1.5"]
129 IGMP_JOIN_RANGE_2
= ["226.1.1.1", "226.1.1.2", "226.1.1.3", "226.1.1.4", "226.1.1.5"]
137 IGMP_JOIN_RANGE_3
= ["227.1.1.1", "227.1.1.2", "227.1.1.3", "227.1.1.4", "227.1.1.5"]
140 intf_r1_s1_addr
= None
142 intf_r2_s1_addr
= None
144 intf_r3_s1_addr
= None
146 intf_i1_s1_addr
= None
149 def setup_module(mod
):
151 Sets up the pytest environment
156 # Required linux kernel version for this suite to run.
157 result
= required_linux_kernel_version("4.19")
158 if result
is not True:
159 pytest
.skip("Kernel requirements are not met")
161 testsuite_run_time
= time
.asctime(time
.localtime(time
.time()))
162 logger
.info("Testsuite start time: {}".format(testsuite_run_time
))
163 logger
.info("=" * 40)
164 logger
.info("Master Topology: \n {}".format(TOPOLOGY
))
166 logger
.info("Running setup_module to create topology")
168 testdir
= os
.path
.dirname(os
.path
.realpath(__file__
))
169 json_file
= "{}/pim_dr_nondr_with_transit_router_topo3.json".format(testdir
)
170 tgen
= Topogen(json_file
, mod
.__name
__)
172 topo
= tgen
.json_topo
173 # ... and here it calls Mininet initialization functions.
175 # Starting topology, create tmp files which are loaded to routers
176 # to start deamons and then start routers
179 # Don"t run this test if we have any failure.
180 if tgen
.routers_have_failure():
181 pytest
.skip(tgen
.errors
)
183 # Creating configuration from JSON
184 build_config_from_json(tgen
, tgen
.json_topo
)
186 # XXX Replace this using "with McastTesterHelper()... " in each test if possible.
188 app_helper
= McastTesterHelper(tgen
)
190 logger
.info("Running setup_module() done")
193 def teardown_module():
194 """Teardown the pytest environment"""
196 logger
.info("Running teardown_module to delete topology")
202 # Stop toplogy and Remove tmp files
206 "Testsuite end time: {}".format(time
.asctime(time
.localtime(time
.time())))
208 logger
.info("=" * 40)
211 #####################################################
215 #####################################################
218 def pre_config_for_receiver_dr_tests(
219 tgen
, topo
, tc_name
, highest_priority
, lowest_priority
222 API to do common pre-configuration for receiver test cases
226 * `tgen`: topogen object
227 * `topo`: input json data
228 * `tc_name`: caller test case name
229 * `highest_priority`: router which will be having highest DR priority
230 * `lowest_priority`: router which will be having lowest DR priority
233 global intf_r1_s1
, intf_r1_s1_addr
, intf_r2_s1
, intf_r2_s1_addr
, intf_i1_s1
, intf_i1_s1_addr
235 step("Configure IGMP and PIM on switch connected receiver nodes")
236 step("Configure PIM on all upstream interfaces")
238 step("Configure link between R1, R2 ,R3 and receiver on" " same vlan")
240 "Make sure {0} is DR initially configuring highest IP on {0} and R2 "
241 "second highest, {1} is lower".format(highest_priority
, lowest_priority
)
244 intf_r1_s1
= topo
["routers"]["r1"]["links"]["s1"]["interface"]
245 intf_r1_s1_addr
= topo
["routers"]["r1"]["links"]["s1"]["ipv4"]
247 intf_r2_s1
= topo
["routers"]["r2"]["links"]["s1"]["interface"]
248 intf_r2_s1_addr
= topo
["routers"]["r2"]["links"]["s1"]["ipv4"]
250 intf_i1_s1
= topo
["routers"]["i1"]["links"]["s1"]["interface"]
251 intf_i1_s1_addr
= topo
["routers"]["i1"]["links"]["s1"]["ipv4"]
253 if lowest_priority
== "r1":
254 lowest_pr_intf
= intf_r1_s1
256 lowest_pr_intf
= intf_r2_s1
258 if highest_priority
== "r1":
259 highest_pr_intf
= intf_r1_s1
261 highest_pr_intf
= intf_r2_s1
269 "ip": SAME_VLAN_IP_1
["ip"],
270 "subnet": SAME_VLAN_IP_1
["subnet"],
281 "ip": SAME_VLAN_IP_2
["ip"],
282 "subnet": SAME_VLAN_IP_2
["subnet"],
293 "ip": SAME_VLAN_IP_4
["ip"],
294 "subnet": SAME_VLAN_IP_4
["subnet"],
302 add_interfaces_to_vlan(tgen
, vlan_input
)
307 "interface {}".format(intf_r1_s1
),
308 "no ip address {}".format(intf_r1_s1_addr
),
314 "interface {}".format(intf_r2_s1
),
315 "no ip address {}".format(intf_r2_s1_addr
),
321 "interface {}".format(intf_i1_s1
),
322 "no ip address {}".format(intf_i1_s1_addr
),
327 result
= apply_raw_config(tgen
, raw_config
)
328 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
333 "interface {}.{}".format(lowest_pr_intf
, VLAN_1
),
334 "ip address {}/{}".format(SAME_VLAN_IP_1
["ip"], SAME_VLAN_IP_1
["cidr"]),
342 "interface {}.{}".format(highest_pr_intf
, VLAN_1
),
343 "ip address {}/{}".format(SAME_VLAN_IP_2
["ip"], SAME_VLAN_IP_2
["cidr"]),
351 "interface {}.{}".format(intf_i1_s1
, VLAN_1
),
352 "ip address {}/{}".format(SAME_VLAN_IP_4
["ip"], SAME_VLAN_IP_4
["cidr"]),
357 result
= apply_raw_config(tgen
, raw_config
)
358 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
360 for dut
, intf
in zip(["r1", "r2"], [intf_r1_s1
, intf_r2_s1
]):
364 "interface {}.{}".format(intf
, VLAN_1
),
365 "ip pim hello {} {}".format(HELLO_TIMER
, HOLD_TIMER
),
369 result
= apply_raw_config(tgen
, raw_config
)
370 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
372 step("Configure R4 as RP on all the nodes for group range 224.0.0.0/24")
379 "rp_addr": topo
["routers"]["r4"]["links"]["lo"]["ipv4"].split(
382 "group_addr_range": GROUP_RANGE_1
,
389 result
= create_pim_config(tgen
, topo
, input_dict
)
390 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
392 step("Send IGMP join for groups 226.1.1.1 to 226.1.1.5")
394 vlan_intf_i1_s1
= "{}.{}".format(intf_i1_s1
, VLAN_1
)
395 result
= app_helper
.run_join("i1", IGMP_JOIN_RANGE_1
, join_intf
=vlan_intf_i1_s1
)
396 assert result
is True, "Testcase {}: Failed Error: {}".format(tc_name
, result
)
398 step("Enable OSPF between r1 and r2")
400 for dut
, intf
in zip(["r1", "r2"], [intf_r1_s1
, intf_r2_s1
]):
404 "interface {}.{}".format(intf
, VLAN_1
),
405 "ip ospf area 0.0.0.0",
406 "ip ospf dead-interval 4",
407 "ip ospf hello-interval 1",
411 result
= apply_raw_config(tgen
, raw_config
)
412 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
414 step("Start traffic from R4 connected source")
416 result
= app_helper
.run_traffic("i2", IGMP_JOIN_RANGE_1
, "r5")
417 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
422 def pre_config_for_source_dr_tests(
423 tgen
, topo
, tc_name
, highest_priority
, lowest_priority
426 API to do common pre-configuration for source test cases
430 * `tgen`: topogen object
431 * `topo`: input json data
432 * `tc_name`: caller test case name
433 * `highest_priority`: router which will be having highest DR priority
434 * `lowest_priority`: router which will be having lowest DR priority
437 global intf_r1_s1
, intf_r1_s1_addr
, intf_r2_s1
, intf_r2_s1_addr
, intf_i1_s1
, intf_i1_s1_addr
439 step("Configure IGMP and PIM on switch connected receiver nodes")
440 step("Configure PIM on all upstream interfaces")
442 step("Configure link between R1, R2 ,R3 and receiver on" " same vlan")
444 "Make sure {0} is DR initially configuring highest IP on {0} and R2 "
445 "second highest, {1} is lower".format(highest_priority
, lowest_priority
)
448 intf_r1_s1
= topo
["routers"]["r1"]["links"]["s1"]["interface"]
449 intf_r1_s1_addr
= topo
["routers"]["r1"]["links"]["s1"]["ipv4"]
451 intf_r2_s1
= topo
["routers"]["r2"]["links"]["s1"]["interface"]
452 intf_r2_s1_addr
= topo
["routers"]["r2"]["links"]["s1"]["ipv4"]
454 intf_i1_s1
= topo
["routers"]["i1"]["links"]["s1"]["interface"]
455 intf_i1_s1_addr
= topo
["routers"]["i1"]["links"]["s1"]["ipv4"]
457 if lowest_priority
== "r1":
458 lowest_pr_intf
= intf_r1_s1
460 lowest_pr_intf
= intf_r2_s1
462 if highest_priority
== "r1":
463 highest_pr_intf
= intf_r1_s1
465 highest_pr_intf
= intf_r2_s1
473 "ip": SAME_VLAN_IP_1
["ip"],
474 "subnet": SAME_VLAN_IP_1
["subnet"],
485 "ip": SAME_VLAN_IP_2
["ip"],
486 "subnet": SAME_VLAN_IP_2
["subnet"],
497 "ip": SAME_VLAN_IP_4
["ip"],
498 "subnet": SAME_VLAN_IP_4
["subnet"],
506 add_interfaces_to_vlan(tgen
, vlan_input
)
511 "interface {}".format(intf_r1_s1
),
512 "no ip address {}".format(intf_r1_s1_addr
),
518 "interface {}".format(intf_r2_s1
),
519 "no ip address {}".format(intf_r2_s1_addr
),
525 "interface {}".format(intf_i1_s1
),
526 "no ip address {}".format(intf_i1_s1_addr
),
531 result
= apply_raw_config(tgen
, raw_config
)
532 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
535 "Configure IGMP and PIM on switch connected receiver nodes , "
536 "configure PIM nbr with hello timer 1"
542 "interface {}.{}".format(lowest_pr_intf
, VLAN_1
),
543 "ip address {}/{}".format(SAME_VLAN_IP_1
["ip"], SAME_VLAN_IP_1
["cidr"]),
549 "interface {}.{}".format(highest_pr_intf
, VLAN_1
),
550 "ip address {}/{}".format(SAME_VLAN_IP_2
["ip"], SAME_VLAN_IP_2
["cidr"]),
556 "interface {}.{}".format(intf_i1_s1
, VLAN_1
),
557 "ip address {}/{}".format(SAME_VLAN_IP_4
["ip"], SAME_VLAN_IP_4
["cidr"]),
562 result
= apply_raw_config(tgen
, raw_config
)
563 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
565 for dut
, intf
in zip(["r1", "r2"], [intf_r1_s1
, intf_r2_s1
]):
569 "interface {}.{}".format(intf
, VLAN_1
),
570 "ip pim hello {} {}".format(HELLO_TIMER
, HOLD_TIMER
),
574 result
= apply_raw_config(tgen
, raw_config
)
575 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
577 step("Configure R4 as RP on all the nodes for group range 224.0.0.0/24")
584 "rp_addr": topo
["routers"]["r4"]["links"]["lo"]["ipv4"].split(
587 "group_addr_range": GROUP_RANGE_1
,
594 result
= create_pim_config(tgen
, topo
, input_dict
)
595 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
597 step("Configure IGMP on R5 port and send IGMP join for groups " "(226.1.1.1-5)")
599 intf_r5_i2
= topo
["routers"]["r5"]["links"]["i2"]["interface"]
601 "r5": {"igmp": {"interfaces": {intf_r5_i2
: {"igmp": {"version": "2"}}}}}
603 result
= create_igmp_config(tgen
, topo
, input_dict
)
604 assert result
is True, "Testcase {}: Failed Error: {}".format(tc_name
, result
)
606 result
= app_helper
.run_join("i2", IGMP_JOIN_RANGE_1
, "r5")
607 assert result
is True, "Testcase {}: Failed Error: {}".format(tc_name
, result
)
609 step("Enable OSPF between r1 and r2")
611 for dut
, intf
in zip(["r1", "r2"], [intf_r1_s1
, intf_r2_s1
]):
615 "interface {}.{}".format(intf
, VLAN_1
),
616 "ip ospf area 0.0.0.0",
617 "ip ospf dead-interval 4",
618 "ip ospf hello-interval 1",
622 result
= apply_raw_config(tgen
, raw_config
)
623 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
625 step("Start traffic from Source node")
627 vlan_intf_i1_s1
= "{}.{}".format(intf_i1_s1
, VLAN_1
)
628 result
= app_helper
.run_traffic("i1", IGMP_JOIN_RANGE_1
, bind_intf
=vlan_intf_i1_s1
)
629 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
634 #####################################################
638 #####################################################
641 def test_mroute_when_transit_router_present_between_rp_and_source_dr_p1(request
):
643 Verify mroutes when transit router present between RP and Source DR
647 tc_name
= request
.node
.name
648 write_test_header(tc_name
)
650 # Creating configuration from JSON
651 app_helper
.stop_all_hosts()
653 check_router_status(tgen
)
654 reset_config_on_routers(tgen
)
655 clear_pim_interface_traffic(tgen
, topo
)
657 # Don"t run this test if we have any failure.
658 if tgen
.routers_have_failure():
659 pytest
.skip(tgen
.errors
)
661 result
= pre_config_for_source_dr_tests(tgen
, topo
, tc_name
, "r1", "r2")
662 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
664 step("Taken care in base config: Add router R6 between RP and R1 , R2")
666 step("R1 is the DR, mroute and upstream created on R1")
668 vlan_intf_r1_s1
= "{}.{}".format(intf_r1_s1
, VLAN_1
)
672 "interfaces": {vlan_intf_r1_s1
: {"drAddress": SAME_VLAN_IP_2
["ip"]}}
676 result
= verify_pim_config(tgen
, input_dict_dr
)
677 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
679 step("On R1 Mroute OIL towards R6, upstream in join Rej Prune state")
681 source_i1
= SAME_VLAN_IP_4
["ip"]
685 "src_address": source_i1
,
686 "oil": topo
["routers"]["r1"]["links"]["r6"]["interface"],
687 "iif": "{}.{}".format(
688 topo
["routers"]["r1"]["links"]["s1"]["interface"], VLAN_1
693 for data
in input_dict_r1
:
694 result
= verify_mroutes(
702 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
704 result
= verify_upstream_iif(
705 tgen
, data
["dut"], data
["iif"], data
["src_address"], IGMP_JOIN_RANGE_1
707 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
710 "R5 have mroute created and traffic is received, verify using "
711 "'show ip mroute json' 'show ip multicast json'"
718 "iif": topo
["routers"]["r5"]["links"]["r4"]["interface"],
719 "oil": topo
["routers"]["r5"]["links"]["i2"]["interface"],
723 "src_address": source_i1
,
724 "iif": topo
["routers"]["r5"]["links"]["r4"]["interface"],
725 "oil": topo
["routers"]["r5"]["links"]["i2"]["interface"],
729 for data
in input_dict_r5
:
730 result
= verify_mroutes(
738 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
740 input_dict_traffic_r5
= {
742 "traffic_received": [topo
["routers"]["r5"]["links"]["r4"]["interface"]],
743 "traffic_sent": [topo
["routers"]["r5"]["links"]["i2"]["interface"]],
747 result
= verify_multicast_traffic(tgen
, input_dict_traffic_r5
)
748 assert result
is True, "Testcase {}:Failed \n Error: {}".format(tc_name
, result
)
750 step("Make R2 as DR configuring higher priority value")
755 "interface {}.{}".format(intf_r1_s1
, VLAN_1
),
756 "no ip address {}/{}".format(
757 SAME_VLAN_IP_2
["ip"], SAME_VLAN_IP_1
["cidr"]
759 "ip address {}/{}".format(SAME_VLAN_IP_1
["ip"], SAME_VLAN_IP_1
["cidr"]),
764 "interface {}.{}".format(intf_r2_s1
, VLAN_1
),
765 "no ip address {}/{}".format(
766 SAME_VLAN_IP_1
["ip"], SAME_VLAN_IP_1
["cidr"]
768 "ip address {}/{}".format(SAME_VLAN_IP_2
["ip"], SAME_VLAN_IP_2
["cidr"]),
773 result
= apply_raw_config(tgen
, raw_config
)
774 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
776 step("R2 is the DR, mroute and upstream created on R2")
778 vlan_intf_r2_s1
= "{}.{}".format(intf_r2_s1
, VLAN_1
)
782 "interfaces": {vlan_intf_r2_s1
: {"drAddress": SAME_VLAN_IP_2
["ip"]}}
786 result
= verify_pim_config(tgen
, input_dict_dr
)
787 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
790 "R5 have mroute created and traffic is received, verify using "
791 "'show ip mroute json' 'show ip multicast json'"
794 for data
in input_dict_r5
:
795 result
= verify_mroutes(
803 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
805 result
= verify_multicast_traffic(tgen
, input_dict_traffic_r5
)
806 assert result
is True, "Testcase {}:Failed \n Error: {}".format(tc_name
, result
)
808 write_test_footer(tc_name
)
811 if __name__
== "__main__":
812 args
= ["-s"] + sys
.argv
[1:]
813 sys
.exit(pytest
.main(args
))