]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py
Merge pull request #10235 from proelbtn/srv6-soft-reconf
[mirror_frr.git] / tests / topotests / multicast_pim_sm_topo2 / test_multicast_pim_sm_topo2.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 multicast pim sm:
25
26 Test steps
27 - Create topology (setup module)
28 - Bring up topology
29
30 Following tests are covered:
31 1. TC_17: Verify (*,G) and (S,G) present and multicast traffic resume,
32 after restart of PIMd daemon
33 2. TC_18: Verify (*,G) and (S,G) present and multicast traffic resume after
34 FRR service stop and start
35 3. TC_10: Verify SPT switchover working when RPT and SPT path is
36 different
37 4. TC_15: Verify (S,G) and (*,G) mroute after shut / no shut of upstream
38 interfaces
39 5. TC_7: Verify mroute detail when receiver is present
40 outside of FRR
41 6. TC_8: Verify mroute when FRR is acting as FHR and LHR
42 7. TC_20: Verify mroute detail when 5 different receiver joining
43 same source
44 8. TC_22: Verify OIL and IIF detail updated in (S,G) mroute after shut
45 and no shut of the source interface
46 """
47
48 import os
49 import sys
50 import time
51 import pytest
52
53 pytestmark = pytest.mark.pimd
54
55 # Save the Current Working Directory to find configuration files.
56 CWD = os.path.dirname(os.path.realpath(__file__))
57 sys.path.append(os.path.join(CWD, "../"))
58 sys.path.append(os.path.join(CWD, "../lib/"))
59
60 # Required to instantiate the topology builder class.
61
62 # pylint: disable=C0413
63 # Import topogen and topotest helpers
64 from lib.topogen import Topogen, get_topogen
65
66 from lib.common_config import (
67 start_topology,
68 write_test_header,
69 write_test_footer,
70 step,
71 reset_config_on_routers,
72 shutdown_bringup_interface,
73 kill_router_daemons,
74 start_router,
75 start_router_daemons,
76 stop_router,
77 required_linux_kernel_version,
78 topo_daemons,
79 )
80 from lib.pim import (
81 create_pim_config,
82 create_igmp_config,
83 verify_igmp_groups,
84 verify_ip_mroutes,
85 get_pim_interface_traffic,
86 verify_upstream_iif,
87 verify_pim_neighbors,
88 verify_pim_state,
89 clear_ip_mroute,
90 clear_ip_pim_interface_traffic,
91 McastTesterHelper,
92 )
93 from lib.topolog import logger
94 from lib.topojson import build_config_from_json
95
96
97 pytestmark = [pytest.mark.pimd]
98
99 TOPOLOGY = """
100
101
102 i4-----c1-------------c2---i5
103 | |
104 | |
105 i1-----l1------r2-----f1---i2
106 | | | |
107 | | | |
108 i7 i6 i3 i8
109
110 Description:
111 i1, i2, i3. i4, i5, i6, i7, i8 - FRR running iperf to send IGMP
112 join and traffic
113 l1 - LHR
114 f1 - FHR
115 r2 - FRR router
116 c1 - FRR router
117 c2 - FRR router
118 """
119
120 # Global variables
121 GROUP_RANGE = "225.0.0.0/8"
122 IGMP_JOIN = "225.1.1.1"
123 GROUP_RANGE_1 = [
124 "225.1.1.1/32",
125 "225.1.1.2/32",
126 "225.1.1.3/32",
127 "225.1.1.4/32",
128 "225.1.1.5/32",
129 ]
130 IGMP_JOIN_RANGE_1 = ["225.1.1.1", "225.1.1.2", "225.1.1.3", "225.1.1.4", "225.1.1.5"]
131 GROUP_RANGE_2 = [
132 "226.1.1.1/32",
133 "226.1.1.2/32",
134 "226.1.1.3/32",
135 "226.1.1.4/32",
136 "226.1.1.5/32",
137 ]
138 IGMP_JOIN_RANGE_2 = ["226.1.1.1", "226.1.1.2", "226.1.1.3", "226.1.1.4", "226.1.1.5"]
139
140 GROUP_RANGE_3 = [
141 "227.1.1.1/32",
142 "227.1.1.2/32",
143 "227.1.1.3/32",
144 "227.1.1.4/32",
145 "227.1.1.5/32",
146 ]
147 IGMP_JOIN_RANGE_3 = ["227.1.1.1", "227.1.1.2", "227.1.1.3", "227.1.1.4", "227.1.1.5"]
148
149
150 def setup_module(mod):
151 """
152 Sets up the pytest environment
153
154 * `mod`: module name
155 """
156
157 # Required linux kernel version for this suite to run.
158 result = required_linux_kernel_version("4.19")
159 if result is not True:
160 pytest.skip("Kernel requirements are not met")
161
162 testsuite_run_time = time.asctime(time.localtime(time.time()))
163 logger.info("Testsuite start time: {}".format(testsuite_run_time))
164 logger.info("=" * 40)
165 logger.info("Master Topology: \n {}".format(TOPOLOGY))
166
167 logger.info("Running setup_module to create topology")
168
169 json_file = "{}/multicast_pim_sm_topo2.json".format(CWD)
170 tgen = Topogen(json_file, mod.__name__)
171 global topo
172 topo = tgen.json_topo
173 # ... and here it calls Mininet initialization functions.
174
175 # get list of daemons needs to be started for this suite.
176 daemons = topo_daemons(tgen, topo)
177
178 # Starting topology, create tmp files which are loaded to routers
179 # to start deamons and then start routers
180 start_topology(tgen, daemons)
181
182 # Don"t run this test if we have any failure.
183 if tgen.routers_have_failure():
184 pytest.skip(tgen.errors)
185
186 # Creating configuration from JSON
187 build_config_from_json(tgen, topo)
188
189 # XXX Replace this using "with McastTesterHelper()... " in each test if possible.
190 global app_helper
191 app_helper = McastTesterHelper(tgen)
192
193 logger.info("Running setup_module() done")
194
195
196 def teardown_module():
197 """Teardown the pytest environment"""
198
199 logger.info("Running teardown_module to delete topology")
200
201 tgen = get_topogen()
202
203 app_helper.cleanup()
204
205 # Stop toplogy and Remove tmp files
206 tgen.stop_topology()
207
208 logger.info(
209 "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
210 )
211 logger.info("=" * 40)
212
213
214 #####################################################
215 #
216 # Testcases
217 #
218 #####################################################
219
220
221 def verify_state_incremented(state_before, state_after):
222 """
223 API to compare interface traffic state incrementing
224
225 Parameters
226 ----------
227 * `state_before` : State dictionary for any particular instance
228 * `state_after` : State dictionary for any particular instance
229 """
230
231 for router, state_data in state_before.items():
232 for state, value in state_data.items():
233 if state_before[router][state] >= state_after[router][state]:
234 errormsg = (
235 "[DUT: %s]: state %s value has not"
236 " incremented, Initial value: %s, "
237 "Current value: %s [FAILED!!]"
238 % (
239 router,
240 state,
241 state_before[router][state],
242 state_after[router][state],
243 )
244 )
245 return errormsg
246
247 logger.info(
248 "[DUT: %s]: State %s value is "
249 "incremented, Initial value: %s, Current value: %s"
250 " [PASSED!!]",
251 router,
252 state,
253 state_before[router][state],
254 state_after[router][state],
255 )
256
257 return True
258
259
260 def test_verify_mroute_and_traffic_when_pimd_restarted_p2(request):
261 """
262 TC_17: Verify (*,G) and (S,G) present and multicast traffic resume,
263 after restart of PIMd daemon
264 """
265
266 tgen = get_topogen()
267 tc_name = request.node.name
268 write_test_header(tc_name)
269
270 # Don"t run this test if we have any failure.
271 if tgen.routers_have_failure():
272 pytest.skip(tgen.errors)
273
274 # Creating configuration from JSON
275 app_helper.stop_all_hosts()
276 clear_ip_mroute(tgen)
277 reset_config_on_routers(tgen)
278 clear_ip_pim_interface_traffic(tgen, topo)
279
280 step("Configure static RP for (226.1.1.1-5) in c1")
281 step("Configure static RP for (232.1.1.1-5) in c2")
282
283 _GROUP_RANGE = GROUP_RANGE_2 + GROUP_RANGE_3
284 _IGMP_JOIN_RANGE = IGMP_JOIN_RANGE_2 + IGMP_JOIN_RANGE_3
285
286 input_dict = {
287 "c1": {
288 "pim": {
289 "rp": [
290 {
291 "rp_addr": topo["routers"]["c1"]["links"]["lo"]["ipv4"].split(
292 "/"
293 )[0],
294 "group_addr_range": GROUP_RANGE_2,
295 }
296 ]
297 }
298 },
299 "c2": {
300 "pim": {
301 "rp": [
302 {
303 "rp_addr": topo["routers"]["c2"]["links"]["lo"]["ipv4"].split(
304 "/"
305 )[0],
306 "group_addr_range": GROUP_RANGE_3,
307 }
308 ]
309 }
310 },
311 }
312
313 result = create_pim_config(tgen, topo, input_dict)
314 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
315
316 step(
317 "Enable IGMP on FRR1 interface and send IGMP join "
318 "(226.1.1.1-5) and (232.1.1.1-5)"
319 )
320 step(
321 "Configure IGMP interface on FRR3 and send IGMP join"
322 " for group (226.1.1.1-5, 232.1.1.1-5)"
323 )
324
325 input_dict = {
326 "f1": {
327 "igmp": {
328 "interfaces": {
329 "f1-i8-eth2": {
330 "igmp": {"version": "2", "query": {"query-interval": 15}}
331 }
332 }
333 }
334 }
335 }
336 result = create_igmp_config(tgen, topo, input_dict)
337 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
338
339 input_join = {"i1": "i1-l1-eth0", "i8": "i8-f1-eth0"}
340
341 for recvr, recvr_intf in input_join.items():
342 result = app_helper.run_join(recvr, _IGMP_JOIN_RANGE, join_intf=recvr_intf)
343 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
344
345 step(
346 "Connect one source to c2 and send multicast traffic all"
347 " the receivers (226.1.1.1-5, 232.1.1.1-5)"
348 )
349 step(
350 "Send multicast traffic from FRR3 to all the receivers "
351 "(226.1.1.1-5, 232.1.1.1-5)"
352 )
353
354 input_src = {"i2": "i2-f1-eth0", "i5": "i5-c2-eth0"}
355
356 for src, src_intf in input_src.items():
357 result = app_helper.run_traffic(src, _IGMP_JOIN_RANGE, bind_intf=src_intf)
358 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
359
360 # Verifying mroutes before PIMd restart, fetching uptime
361
362 source = topo["routers"]["i2"]["links"]["f1"]["ipv4"].split("/")[0]
363 input_dict = [
364 {"dut": "f1", "src_address": "*", "iif": "f1-c2-eth0", "oil": "f1-i8-eth2"},
365 {"dut": "f1", "src_address": source, "iif": "f1-i2-eth1", "oil": "f1-i8-eth2"},
366 ]
367 for data in input_dict:
368 result = verify_ip_mroutes(
369 tgen,
370 data["dut"],
371 data["src_address"],
372 _IGMP_JOIN_RANGE,
373 data["iif"],
374 data["oil"],
375 )
376 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
377
378 for data in input_dict:
379 result = verify_upstream_iif(
380 tgen, data["dut"], data["iif"], data["src_address"], _IGMP_JOIN_RANGE
381 )
382 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
383
384 step("Restart Pimd process on FRR3 node")
385 kill_router_daemons(tgen, "f1", ["pimd"])
386 start_router_daemons(tgen, "f1", ["pimd"])
387
388 for data in input_dict:
389 result = verify_ip_mroutes(
390 tgen,
391 data["dut"],
392 data["src_address"],
393 _IGMP_JOIN_RANGE,
394 data["iif"],
395 data["oil"],
396 )
397 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
398
399 step(
400 "After restart of PIMd verify pim nbr is up , IGMP groups"
401 " received , and (*,G) (S,G) entries populated again ,"
402 " Verify using 'show ip pim neighbor' , 'show ip igmp groups'"
403 " 'show ip mroute'"
404 )
405
406 result = verify_pim_neighbors(tgen, topo)
407 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
408
409 dut = "f1"
410 interface = "f1-i8-eth2"
411 result = verify_igmp_groups(tgen, dut, interface, _IGMP_JOIN_RANGE)
412 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
413
414 for data in input_dict:
415 result = verify_upstream_iif(
416 tgen, data["dut"], data["iif"], data["src_address"], _IGMP_JOIN_RANGE
417 )
418 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
419
420 step("Stop the traffic and restart PIMd immediately on FRR3 node")
421 dut = "i2"
422 intf = "i2-f1-eth0"
423 shutdown_bringup_interface(tgen, dut, intf, False)
424
425 kill_router_daemons(tgen, "f1", ["pimd"])
426 start_router_daemons(tgen, "f1", ["pimd"])
427
428 step(
429 "After PIM process come , all the none of (S,G) mroute should"
430 " present on FRR3 'show ip mroute' "
431 )
432
433 input_dict = [
434 {"dut": "f1", "src_address": "*", "iif": "f1-c2-eth0", "oil": "f1-i8-eth2"}
435 ]
436 for data in input_dict:
437 result = verify_ip_mroutes(
438 tgen,
439 data["dut"],
440 data["src_address"],
441 _IGMP_JOIN_RANGE,
442 data["iif"],
443 data["oil"],
444 )
445 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
446
447 input_dict = [
448 {"dut": "f1", "src_address": source, "iif": "f1-i2-eth1", "oil": "none"}
449 ]
450 for data in input_dict:
451 result = verify_ip_mroutes(
452 tgen,
453 data["dut"],
454 data["src_address"],
455 _IGMP_JOIN_RANGE,
456 data["iif"],
457 data["oil"],
458 expected=False,
459 )
460 assert (
461 result is not True
462 ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
463 tc_name, result
464 )
465 logger.info("Expected Behavior: {}".format(result))
466
467 write_test_footer(tc_name)
468
469
470 def test_verify_mroute_and_traffic_when_frr_restarted_p2(request):
471 """
472 TC_18: Verify (*,G) and (S,G) present and multicast traffic resume after
473 FRR service stop and start
474 """
475
476 tgen = get_topogen()
477 tc_name = request.node.name
478 write_test_header(tc_name)
479
480 # Don"t run this test if we have any failure.
481 if tgen.routers_have_failure():
482 pytest.skip(tgen.errors)
483
484 # Creating configuration from JSON
485 app_helper.stop_all_hosts()
486 clear_ip_mroute(tgen)
487 reset_config_on_routers(tgen)
488 clear_ip_pim_interface_traffic(tgen, topo)
489
490 step("Configure static RP for (226.1.1.1-5) in c1")
491 step("Configure static RP for (232.1.1.1-5) in c2")
492
493 _GROUP_RANGE = GROUP_RANGE_2 + GROUP_RANGE_3
494 _IGMP_JOIN_RANGE = IGMP_JOIN_RANGE_2 + IGMP_JOIN_RANGE_3
495
496 input_dict = {
497 "c1": {
498 "pim": {
499 "rp": [
500 {
501 "rp_addr": topo["routers"]["c1"]["links"]["lo"]["ipv4"].split(
502 "/"
503 )[0],
504 "group_addr_range": GROUP_RANGE_2,
505 }
506 ]
507 }
508 },
509 "c2": {
510 "pim": {
511 "rp": [
512 {
513 "rp_addr": topo["routers"]["c2"]["links"]["lo"]["ipv4"].split(
514 "/"
515 )[0],
516 "group_addr_range": GROUP_RANGE_3,
517 }
518 ]
519 }
520 },
521 }
522
523 result = create_pim_config(tgen, topo, input_dict)
524 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
525
526 step(
527 "Enable IGMP on FRR1 interface and send IGMP join "
528 "(226.1.1.1-5) and (232.1.1.1-5)"
529 )
530 step(
531 "Configure IGMP interface on FRR3 and send IGMP join"
532 " for group (226.1.1.1-5, 232.1.1.1-5)"
533 )
534
535 input_dict = {
536 "f1": {
537 "igmp": {
538 "interfaces": {
539 "f1-i8-eth2": {
540 "igmp": {"version": "2", "query": {"query-interval": 15}}
541 }
542 }
543 }
544 }
545 }
546 result = create_igmp_config(tgen, topo, input_dict)
547 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
548
549 input_join = {"i1": "i1-l1-eth0", "i8": "i8-f1-eth0"}
550
551 for recvr, recvr_intf in input_join.items():
552 result = app_helper.run_join(recvr, _IGMP_JOIN_RANGE, join_intf=recvr_intf)
553 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
554
555 step(
556 "Connect one source to c2 and send multicast traffic all"
557 " the receivers (226.1.1.1-5, 232.1.1.1-5)"
558 )
559 step(
560 "Send multicast traffic from FRR3 to all the receivers "
561 "(226.1.1.1-5, 232.1.1.1-5)"
562 )
563
564 input_src = {"i2": "i2-f1-eth0", "i5": "i5-c2-eth0"}
565
566 for src, src_intf in input_src.items():
567 result = app_helper.run_traffic(src, _IGMP_JOIN_RANGE, bind_intf=src_intf)
568 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
569
570 step("Verifying mroutes before FRR restart, fetching uptime")
571
572 source = topo["routers"]["i2"]["links"]["f1"]["ipv4"].split("/")[0]
573 input_dict = [
574 {"dut": "f1", "src_address": "*", "iif": "f1-c2-eth0", "oil": "f1-i8-eth2"},
575 {"dut": "f1", "src_address": source, "iif": "f1-i2-eth1", "oil": "f1-i8-eth2"},
576 ]
577 for data in input_dict:
578 result = verify_ip_mroutes(
579 tgen,
580 data["dut"],
581 data["src_address"],
582 _IGMP_JOIN_RANGE,
583 data["iif"],
584 data["oil"],
585 )
586 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
587
588 for data in input_dict:
589 result = verify_upstream_iif(
590 tgen, data["dut"], data["iif"], data["src_address"], _IGMP_JOIN_RANGE
591 )
592 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
593
594 step("Stop and Start the FRR services on FRR3 node")
595 stop_router(tgen, "f1")
596 start_router(tgen, "f1")
597
598 for data in input_dict:
599 result = verify_ip_mroutes(
600 tgen,
601 data["dut"],
602 data["src_address"],
603 _IGMP_JOIN_RANGE,
604 data["iif"],
605 data["oil"],
606 )
607 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
608
609 step(
610 "After stop and start of FRR service verify pim nbr is up "
611 "IGMP groups received , and (*,G) (S,G) entries populated again"
612 " Verify using 'show ip pim neighbor' , 'show ip igmp groups'"
613 " 'show ip mroute'"
614 )
615
616 result = verify_pim_neighbors(tgen, topo)
617 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
618
619 dut = "f1"
620 interface = "f1-i8-eth2"
621 result = verify_igmp_groups(tgen, dut, interface, _IGMP_JOIN_RANGE)
622 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
623
624 for data in input_dict:
625 result = verify_upstream_iif(
626 tgen, data["dut"], data["iif"], data["src_address"], _IGMP_JOIN_RANGE
627 )
628 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
629
630 step("Stop the traffic and stop and start the FRR services on" " FRR3 node")
631 shutdown_bringup_interface(tgen, "i2", "i2-f1-eth0", False)
632
633 stop_router(tgen, "f1")
634 start_router(tgen, "f1")
635
636 step(
637 "After stop and start of FRR services , all the none of (S,G)"
638 " mroute should present on FRR3 node verify using "
639 "'show ip mroute'"
640 )
641
642 input_dict = [
643 {"dut": "f1", "src_address": "*", "iif": "f1-c2-eth0", "oil": "f1-i8-eth2"}
644 ]
645 for data in input_dict:
646 result = verify_ip_mroutes(
647 tgen,
648 data["dut"],
649 data["src_address"],
650 _IGMP_JOIN_RANGE,
651 data["iif"],
652 data["oil"],
653 )
654 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
655
656 input_dict = [
657 {"dut": "f1", "src_address": source, "iif": "f1-i2-eth1", "oil": "none"}
658 ]
659 for data in input_dict:
660 result = verify_ip_mroutes(
661 tgen,
662 data["dut"],
663 data["src_address"],
664 _IGMP_JOIN_RANGE,
665 data["iif"],
666 data["oil"],
667 expected=False,
668 )
669 assert (
670 result is not True
671 ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
672 tc_name, result
673 )
674 logger.info("Expected Behavior: {}".format(result))
675
676 write_test_footer(tc_name)
677
678
679 def test_verify_SPT_switchover_when_RPT_and_SPT_path_is_different_p0(request):
680 """
681 TC_10: Verify SPT switchover working when RPT and SPT path is
682 different
683 """
684
685 tgen = get_topogen()
686 tc_name = request.node.name
687 write_test_header(tc_name)
688
689 # Don"t run this test if we have any failure.
690 if tgen.routers_have_failure():
691 pytest.skip(tgen.errors)
692
693 # Creating configuration from JSON
694 app_helper.stop_all_hosts()
695 clear_ip_mroute(tgen)
696 reset_config_on_routers(tgen)
697 clear_ip_pim_interface_traffic(tgen, topo)
698
699 step("Configure static RP for (226.1.1.1-5) and " "(232.1.1.1-5) in c2")
700
701 _GROUP_RANGE = GROUP_RANGE_2 + GROUP_RANGE_3
702 _IGMP_JOIN_RANGE = IGMP_JOIN_RANGE_2 + IGMP_JOIN_RANGE_3
703
704 input_dict = {
705 "c2": {
706 "pim": {
707 "rp": [
708 {
709 "rp_addr": topo["routers"]["c2"]["links"]["lo"]["ipv4"].split(
710 "/"
711 )[0],
712 "group_addr_range": _GROUP_RANGE,
713 }
714 ]
715 }
716 }
717 }
718
719 result = create_pim_config(tgen, topo, input_dict)
720 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
721
722 step(
723 "Enable IGMP on FRR1 interface and send IGMP join "
724 "(226.1.1.1-5) and (232.1.1.1-5)"
725 )
726
727 result = app_helper.run_join("i1", _IGMP_JOIN_RANGE, "l1")
728 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
729
730 step("Send multicast traffic from FRR3 to '226.1.1.1-5'" ", '232.1.1.1-5' receiver")
731
732 step("registerRx and registerStopTx value before traffic sent")
733 state_dict = {"c2": {"c2-f1-eth1": ["registerRx", "registerStopTx"]}}
734 state_before = get_pim_interface_traffic(tgen, state_dict)
735 assert isinstance(
736 state_before, dict
737 ), "Testcase {} : Failed \n state_before is not dictionary \nError: {}".format(
738 tc_name, result
739 )
740
741 result = app_helper.run_traffic("i2", _IGMP_JOIN_RANGE, "f1")
742 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
743
744 step(
745 "Verify in FRR3 sending initial packet to RP using"
746 " 'show ip mroute' and mroute OIL is towards RP."
747 )
748
749 result = verify_ip_mroutes(
750 tgen,
751 "f1",
752 "10.0.5.2",
753 _IGMP_JOIN_RANGE,
754 "f1-i2-eth1",
755 ["f1-c2-eth0", "f1-r2-eth3"],
756 )
757 assert result is True, "Testcase {} : " "Failed Error: {}".format(tc_name, result)
758
759 result = verify_ip_mroutes(
760 tgen, "f1", "10.0.5.2", _IGMP_JOIN_RANGE, "f1-i2-eth1", "f1-r2-eth3"
761 )
762 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
763
764 step(
765 " After spt switchover traffic is flowing between"
766 " (LHR(FRR1)-FHR(FRR3)) and (S,G) OIL is updated toward FRR1"
767 " 'show ip mroute' and 'show ip pim upstream'"
768 )
769
770 source = topo["routers"]["i2"]["links"]["f1"]["ipv4"].split("/")[0]
771 input_dict = [
772 {"dut": "f1", "src_address": source, "iif": "f1-i2-eth1", "oil": "f1-r2-eth3"},
773 {"dut": "l1", "src_address": source, "iif": "l1-r2-eth4", "oil": "l1-i1-eth1"},
774 ]
775 for data in input_dict:
776 result = verify_ip_mroutes(
777 tgen,
778 data["dut"],
779 data["src_address"],
780 _IGMP_JOIN_RANGE,
781 data["iif"],
782 data["oil"],
783 )
784 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
785
786 for data in input_dict:
787 result = verify_upstream_iif(
788 tgen, data["dut"], data["iif"], data["src_address"], _IGMP_JOIN_RANGE
789 )
790 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
791
792 step("Stop the traffic to all the receivers")
793
794 app_helper.stop_host("i2")
795
796 step(
797 "Null register packet being send periodically from FRR3 to RP, "
798 "verify using show ip mroute on RP, have (S, G) entries null OIL"
799 " 'show ip mroute' and verify show ip pim interface traffic"
800 "(In RP Register msg should be received and Register stop should"
801 " be transmitted)"
802 )
803 input_dict = [
804 {"dut": "c2", "src_address": source, "iif": "c2-f1-eth1", "oil": "none"}
805 ]
806 for data in input_dict:
807 result = verify_ip_mroutes(
808 tgen,
809 data["dut"],
810 data["src_address"],
811 _IGMP_JOIN_RANGE,
812 data["iif"],
813 data["oil"],
814 )
815 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
816
817 step("registerRx and registerStopTx value after traffic sent")
818 state_after = get_pim_interface_traffic(tgen, state_dict)
819 assert isinstance(
820 state_after, dict
821 ), "Testcase {} : Failed \n state_before is not dictionary \nError: {}".format(
822 tc_name, result
823 )
824
825 result = verify_state_incremented(state_before, state_after)
826 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
827
828 write_test_footer(tc_name)
829
830
831 def test_verify_mroute_after_shut_noshut_of_upstream_interface_p1(request):
832 """
833 TC_15: Verify (S,G) and (*,G) mroute after shut / no shut of upstream
834 interfaces
835 """
836
837 tgen = get_topogen()
838 tc_name = request.node.name
839 write_test_header(tc_name)
840
841 # Don"t run this test if we have any failure.
842 if tgen.routers_have_failure():
843 pytest.skip(tgen.errors)
844
845 # Creating configuration from JSON
846 app_helper.stop_all_hosts()
847 clear_ip_mroute(tgen)
848 reset_config_on_routers(tgen)
849 clear_ip_pim_interface_traffic(tgen, topo)
850
851 step("Configure static RP for (226.1.1.1-5) in c1")
852 step("Configure static RP for (232.1.1.1-5) in c2")
853
854 _GROUP_RANGE = GROUP_RANGE_2 + GROUP_RANGE_3
855 _IGMP_JOIN_RANGE = IGMP_JOIN_RANGE_2 + IGMP_JOIN_RANGE_3
856
857 input_dict = {
858 "c1": {
859 "pim": {
860 "rp": [
861 {
862 "rp_addr": topo["routers"]["c1"]["links"]["lo"]["ipv4"].split(
863 "/"
864 )[0],
865 "group_addr_range": GROUP_RANGE_2,
866 }
867 ]
868 }
869 },
870 "c2": {
871 "pim": {
872 "rp": [
873 {
874 "rp_addr": topo["routers"]["c2"]["links"]["lo"]["ipv4"].split(
875 "/"
876 )[0],
877 "group_addr_range": GROUP_RANGE_3,
878 }
879 ]
880 }
881 },
882 }
883
884 result = create_pim_config(tgen, topo, input_dict)
885 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
886
887 step(
888 "Enable IGMP on FRR1 interface and send IGMP join "
889 "(226.1.1.1-5) and (232.1.1.1-5)"
890 )
891 step(
892 "Configure IGMP interface on FRR3 and send IGMP join"
893 " for group (226.1.1.1-5, 232.1.1.1-5)"
894 )
895
896 input_dict = {
897 "f1": {
898 "igmp": {
899 "interfaces": {
900 "f1-i8-eth2": {
901 "igmp": {"version": "2", "query": {"query-interval": 15}}
902 }
903 }
904 }
905 }
906 }
907 result = create_igmp_config(tgen, topo, input_dict)
908 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
909
910 input_join = {"i1": "i1-l1-eth0", "i8": "i8-f1-eth0"}
911
912 for recvr, recvr_intf in input_join.items():
913 result = app_helper.run_join(recvr, _IGMP_JOIN_RANGE, join_intf=recvr_intf)
914 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
915
916 step(
917 "Connect one source to c2 and send multicast traffic all"
918 " the receivers (226.1.1.1-5, 232.1.1.1-5)"
919 )
920 step(
921 "Send multicast traffic from FRR3 to all the receivers "
922 "(226.1.1.1-5, 232.1.1.1-5)"
923 )
924
925 input_src = {"i2": "i2-f1-eth0", "i5": "i5-c2-eth0"}
926
927 for src, src_intf in input_src.items():
928 result = app_helper.run_traffic(src, _IGMP_JOIN_RANGE, bind_intf=src_intf)
929 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
930
931 step(
932 "FRR3 (S,G) has one OIL for local receiver one toward c2"
933 " verify 'show ip mroute' and 'show ip pim upstream'"
934 )
935
936 source = topo["routers"]["i2"]["links"]["f1"]["ipv4"].split("/")[0]
937 input_dict = [
938 {"dut": "f1", "src_address": "*", "iif": "f1-c2-eth0", "oil": "f1-i8-eth2"},
939 {"dut": "f1", "src_address": source, "iif": "f1-i2-eth1", "oil": "f1-i8-eth2"},
940 ]
941 for data in input_dict:
942 result = verify_ip_mroutes(
943 tgen,
944 data["dut"],
945 data["src_address"],
946 IGMP_JOIN_RANGE_2,
947 data["iif"],
948 data["oil"],
949 )
950 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
951
952 for data in input_dict:
953 result = verify_upstream_iif(
954 tgen, data["dut"], data["iif"], data["src_address"], IGMP_JOIN_RANGE_2
955 )
956 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
957
958 step("Shut and No shut interface connected from FHR (FRR3)" " to c2")
959 dut = "f1"
960 intf = "f1-c2-eth0"
961 shutdown_bringup_interface(tgen, dut, intf, False)
962 shutdown_bringup_interface(tgen, dut, intf, True)
963
964 step("Shut and No shut interface connected from LHR (FRR1)" " to c1")
965 dut = "l1"
966 intf = "l1-c1-eth0"
967 shutdown_bringup_interface(tgen, dut, intf, False)
968 shutdown_bringup_interface(tgen, dut, intf, True)
969
970 for data in input_dict:
971 result = verify_ip_mroutes(
972 tgen,
973 data["dut"],
974 data["src_address"],
975 IGMP_JOIN_RANGE_2,
976 data["iif"],
977 data["oil"],
978 )
979 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
980
981 step("Shut and No shut FRR1 and FRR3 interface")
982 shutdown_bringup_interface(tgen, "l1", "l1-r2-eth4", False)
983 shutdown_bringup_interface(tgen, dut, intf, True)
984
985 shutdown_bringup_interface(tgen, "f1", "f1-r2-eth3", False)
986 shutdown_bringup_interface(tgen, dut, intf, True)
987
988 step(
989 "After shut/no shut of interface , verify traffic resume to all"
990 "the receivers (S,G) OIL update for all the receivers"
991 )
992
993 for data in input_dict:
994 result = verify_ip_mroutes(
995 tgen,
996 data["dut"],
997 data["src_address"],
998 IGMP_JOIN_RANGE_2,
999 data["iif"],
1000 data["oil"],
1001 )
1002 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1003
1004 step(
1005 "Shut FRR1, FRR3 interface , clear mroute in FRR1"
1006 " and No shut FRR1, FRR3 interface "
1007 )
1008 dut = "l1"
1009 intf = "l1-r2-eth4"
1010 shutdown_bringup_interface(tgen, dut, intf, False)
1011
1012 dut = "f1"
1013 intf = "f1-r2-eth3"
1014 shutdown_bringup_interface(tgen, dut, intf, False)
1015
1016 dut = "l1"
1017 intf = "l1-r2-eth4"
1018 shutdown_bringup_interface(tgen, dut, intf, True)
1019
1020 dut = "f1"
1021 intf = "f1-r2-eth3"
1022 shutdown_bringup_interface(tgen, dut, intf, True)
1023
1024 clear_ip_mroute(tgen, "l1")
1025 clear_ip_mroute(tgen, "l1")
1026
1027 step(
1028 "After no shut, verify traffic resume to all the receivers"
1029 " (S,G) OIL update for all the receivers"
1030 )
1031
1032 for data in input_dict:
1033 result = verify_ip_mroutes(
1034 tgen,
1035 data["dut"],
1036 data["src_address"],
1037 IGMP_JOIN_RANGE_2,
1038 data["iif"],
1039 data["oil"],
1040 )
1041 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1042
1043 step(
1044 "Shut and no shut upstream interface from FRR1 to FRR2 and "
1045 "cisco immediate after mroute/upstream got cleared"
1046 )
1047
1048 dut = "l1"
1049 intf_l1_r2 = "l1-r2-eth4"
1050 shutdown_bringup_interface(tgen, dut, intf_l1_r2, False)
1051
1052 intf_l1_c1 = "l1-c1-eth0"
1053 shutdown_bringup_interface(tgen, dut, intf_l1_c1, False)
1054
1055 result = verify_upstream_iif(
1056 tgen, "l1", "Unknown", source, IGMP_JOIN_RANGE_2, expected=False
1057 )
1058 assert result is not True, (
1059 "Testcase {} : Failed Error: \n "
1060 "mroutes are still present, after waiting for 10 mins".format(tc_name)
1061 )
1062
1063 step("No shut the Source interface just after the upstream is expired" " from FRR1")
1064 shutdown_bringup_interface(tgen, dut, intf_l1_r2, True)
1065 shutdown_bringup_interface(tgen, dut, intf_l1_c1, True)
1066
1067 for data in input_dict:
1068 result = verify_ip_mroutes(
1069 tgen,
1070 data["dut"],
1071 data["src_address"],
1072 IGMP_JOIN_RANGE_2,
1073 data["iif"],
1074 data["oil"],
1075 )
1076 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1077
1078 step("Stop the traffic to all the receivers")
1079 app_helper.stop_all_hosts()
1080
1081 for data in input_dict:
1082 result = verify_ip_mroutes(
1083 tgen,
1084 data["dut"],
1085 data["src_address"],
1086 IGMP_JOIN_RANGE_2,
1087 data["iif"],
1088 data["oil"],
1089 expected=False,
1090 )
1091 assert (
1092 result is not True
1093 ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
1094 tc_name, result
1095 )
1096 logger.info("Expected Behavior: {}".format(result))
1097
1098 write_test_footer(tc_name)
1099
1100
1101 def test_verify_mroute_when_receiver_is_outside_frr_p0(request):
1102 """
1103 TC_7: Verify mroute detail when receiver is present
1104 outside of FRR
1105 """
1106
1107 tgen = get_topogen()
1108 tc_name = request.node.name
1109 write_test_header(tc_name)
1110
1111 # Don"t run this test if we have any failure.
1112 if tgen.routers_have_failure():
1113 pytest.skip(tgen.errors)
1114
1115 # Creating configuration from JSON
1116 app_helper.stop_all_hosts()
1117 clear_ip_mroute(tgen)
1118 reset_config_on_routers(tgen)
1119 clear_ip_pim_interface_traffic(tgen, topo)
1120
1121 step("Configure static RP on c1 for group range " "(226.1.1.1-5) and (232.1.1.1-5)")
1122
1123 _GROUP_RANGE = GROUP_RANGE_2 + GROUP_RANGE_3
1124 _IGMP_JOIN_RANGE = IGMP_JOIN_RANGE_2 + IGMP_JOIN_RANGE_3
1125
1126 input_dict = {
1127 "c1": {
1128 "pim": {
1129 "rp": [
1130 {
1131 "rp_addr": topo["routers"]["c1"]["links"]["lo"]["ipv4"].split(
1132 "/"
1133 )[0],
1134 "group_addr_range": _GROUP_RANGE,
1135 }
1136 ]
1137 }
1138 }
1139 }
1140
1141 result = create_pim_config(tgen, topo, input_dict)
1142 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1143
1144 step(
1145 "Enable IGMP on FRR1 interface and send IGMP join"
1146 " (226.1.1.1-5) and (232.1.1.1-5)"
1147 )
1148 result = app_helper.run_join("i1", _IGMP_JOIN_RANGE, "l1")
1149 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1150
1151 step(
1152 "Send multicast traffic from FRR3 to all the receivers "
1153 "(226.1.1.1-5) and (232.1.1.1-5)"
1154 )
1155 result = app_helper.run_traffic("i2", _IGMP_JOIN_RANGE, "f1")
1156 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1157
1158 step(
1159 "Configure one more receiver in c2 enable IGMP and send"
1160 " join (226.1.1.1-5) and (232.1.1.1-5)"
1161 )
1162 input_dict = {
1163 "c2": {
1164 "igmp": {
1165 "interfaces": {
1166 "c2-i5-eth2": {
1167 "igmp": {"version": "2", "query": {"query-interval": 15}}
1168 }
1169 }
1170 }
1171 }
1172 }
1173 result = create_igmp_config(tgen, topo, input_dict)
1174 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1175
1176 result = app_helper.run_join("i5", _IGMP_JOIN_RANGE, "c2")
1177 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1178
1179 step("FRR1 has 10 (*.G) and 10 (S,G) verify using 'show ip mroute count'")
1180 step(
1181 "All the receiver are receiving traffic on FRR1 and (S,G) OIL is toward"
1182 "receivers, verify using 'show ip mroute' 'show ip pim upstream'"
1183 )
1184 step(
1185 "All the receiver are receiving traffic on c2 and (S,G) OIL is "
1186 "toward receivers, verify using 'show ip mroute' 'show ip pim upstream'"
1187 )
1188
1189 source = topo["routers"]["i2"]["links"]["f1"]["ipv4"].split("/")[0]
1190 input_dict = [
1191 {"dut": "l1", "src_address": "*", "iif": "l1-c1-eth0", "oil": "l1-i1-eth1"},
1192 {"dut": "l1", "src_address": source, "iif": "l1-r2-eth4", "oil": "l1-i1-eth1"},
1193 {"dut": "c2", "src_address": "*", "iif": "c2-c1-eth0", "oil": "c2-i5-eth2"},
1194 {"dut": "c2", "src_address": source, "iif": "c2-f1-eth1", "oil": "c2-i5-eth2"},
1195 ]
1196 for data in input_dict:
1197 result = verify_ip_mroutes(
1198 tgen,
1199 data["dut"],
1200 data["src_address"],
1201 _IGMP_JOIN_RANGE,
1202 data["iif"],
1203 data["oil"],
1204 )
1205 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1206
1207 step(
1208 "FRR3 has (S,G) OIL created toward c1/c2 receiver and FRR1 receiver"
1209 "'show ip pim state'"
1210 )
1211 input_dict = [
1212 {"dut": "f1", "src_address": source, "iif": "f1-i2-eth1", "oil": "f1-c2-eth0"},
1213 {"dut": "f1", "src_address": source, "iif": "f1-i2-eth1", "oil": "f1-r2-eth3"},
1214 ]
1215 for data in input_dict:
1216 result = verify_pim_state(
1217 tgen,
1218 data["dut"],
1219 data["iif"],
1220 data["oil"],
1221 _IGMP_JOIN_RANGE,
1222 data["src_address"],
1223 )
1224 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1225
1226 for data in input_dict:
1227 result = verify_upstream_iif(
1228 tgen, data["dut"], data["iif"], data["src_address"], _IGMP_JOIN_RANGE
1229 )
1230 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1231
1232 write_test_footer(tc_name)
1233
1234
1235 def test_verify_mroute_when_FRR_is_FHR_and_LHR_p0(request):
1236 """
1237 TC_8: Verify mroute when FRR is acting as FHR and LHR
1238 """
1239
1240 tgen = get_topogen()
1241 tc_name = request.node.name
1242 write_test_header(tc_name)
1243
1244 # Don"t run this test if we have any failure.
1245 if tgen.routers_have_failure():
1246 pytest.skip(tgen.errors)
1247
1248 # Creating configuration from JSON
1249 app_helper.stop_all_hosts()
1250 clear_ip_mroute(tgen)
1251 reset_config_on_routers(tgen)
1252 clear_ip_pim_interface_traffic(tgen, topo)
1253
1254 step("Configure static RP for group range (226.1.1.1-5) and " "(232.1.1.1-5) on c1")
1255 _GROUP_RANGE = GROUP_RANGE_2 + GROUP_RANGE_3
1256 _IGMP_JOIN_RANGE = IGMP_JOIN_RANGE_2 + IGMP_JOIN_RANGE_3
1257
1258 input_dict = {
1259 "c1": {
1260 "pim": {
1261 "rp": [
1262 {
1263 "rp_addr": topo["routers"]["c1"]["links"]["lo"]["ipv4"].split(
1264 "/"
1265 )[0],
1266 "group_addr_range": _GROUP_RANGE,
1267 }
1268 ]
1269 }
1270 }
1271 }
1272
1273 result = create_pim_config(tgen, topo, input_dict)
1274 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1275
1276 step(
1277 "Enable IGMP on FRR1 interface and send IGMP join (226.1.1.1-5)"
1278 " and (232.1.1.1-5)"
1279 )
1280 step(
1281 "Configure receiver on FRR3 with igmp and pim enabled and "
1282 "send IGMP join (226.1.1.1-5) and (232.1.1.1-5)"
1283 )
1284 step(
1285 "Send multicast traffic from FRR3 to all the receivers "
1286 "(226.1.1.1-5) and (232.1.1.1-5)"
1287 )
1288
1289 step("Send IGMP join (226.1.1.1-5, 232.1.1.1-5) to LHR(l1)")
1290 result = app_helper.run_join("i1", _IGMP_JOIN_RANGE, "l1")
1291 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1292
1293 step("Send multicast traffic from FRR3 to '226.1.1.1-5'" ", '232.1.1.1-5' receiver")
1294 result = app_helper.run_traffic("i2", _IGMP_JOIN_RANGE, "f1")
1295 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1296
1297 step(
1298 "Configure receiver in f1 enable IGMP and send"
1299 " join (226.1.1.1-5) and (232.1.1.1-5)"
1300 )
1301
1302 step("Configure one IGMP interface on f1 node and send IGMP" " join (225.1.1.1)")
1303 input_dict = {
1304 "f1": {
1305 "igmp": {
1306 "interfaces": {
1307 "f1-i8-eth2": {
1308 "igmp": {"version": "2", "query": {"query-interval": 15}}
1309 }
1310 }
1311 }
1312 }
1313 }
1314 result = create_igmp_config(tgen, topo, input_dict)
1315 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1316
1317 result = app_helper.run_join("i8", _IGMP_JOIN_RANGE, "f1")
1318 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1319 step(
1320 "l1 and f1 has 10 IGMP groups (226.1.1.1-5, 232.1.1.1-5),"
1321 " verify using 'show ip igmp groups'"
1322 )
1323 dut = "l1"
1324 interface = "l1-i1-eth1"
1325 result = verify_igmp_groups(tgen, dut, interface, _IGMP_JOIN_RANGE)
1326 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1327
1328 dut = "f1"
1329 interface = "f1-i8-eth2"
1330 result = verify_igmp_groups(tgen, dut, interface, _IGMP_JOIN_RANGE)
1331 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1332
1333 step(
1334 "l1 , f1 has 10 (*,G) and 10 (S,G) for groups "
1335 "(226.1.1.1-5, 232.1.1.1-5), verify using "
1336 " 'show ip mroute'"
1337 )
1338
1339 source = topo["routers"]["i2"]["links"]["f1"]["ipv4"].split("/")[0]
1340 input_dict = [
1341 {"dut": "f1", "src_address": "*", "iif": "f1-c2-eth0", "oil": "f1-i8-eth2"},
1342 {"dut": "f1", "src_address": source, "iif": "f1-i2-eth1", "oil": "f1-r2-eth3"},
1343 {"dut": "l1", "src_address": "*", "iif": "l1-c1-eth0", "oil": "l1-i1-eth1"},
1344 {"dut": "l1", "src_address": source, "iif": "l1-r2-eth4", "oil": "l1-i1-eth1"},
1345 ]
1346 for data in input_dict:
1347 result = verify_ip_mroutes(
1348 tgen,
1349 data["dut"],
1350 data["src_address"],
1351 _IGMP_JOIN_RANGE,
1352 data["iif"],
1353 data["oil"],
1354 )
1355 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1356
1357 step("Join timer is running in FHR and LHR , verify using" " 'show ip pim state'")
1358
1359 for data in input_dict:
1360 result = verify_pim_state(
1361 tgen,
1362 data["dut"],
1363 data["iif"],
1364 data["oil"],
1365 _IGMP_JOIN_RANGE,
1366 data["src_address"],
1367 )
1368 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1369
1370 # Stop the multicast traffic
1371 step("Stop the traffic to all the receivers")
1372 app_helper.stop_all_hosts()
1373
1374 step(
1375 "After traffic stopped , verify (*,G) entries are not flushed"
1376 " out from FRR1 node verify using 'show ip mroute' "
1377 )
1378
1379 input_dict = [
1380 {"dut": "f1", "src_address": "*", "iif": "f1-c2-eth0", "oil": "f1-i8-eth2"},
1381 {"dut": "l1", "src_address": "*", "iif": "l1-c1-eth0", "oil": "l1-i1-eth1"},
1382 ]
1383 for data in input_dict:
1384 result = verify_ip_mroutes(
1385 tgen,
1386 data["dut"],
1387 data["src_address"],
1388 _IGMP_JOIN_RANGE,
1389 data["iif"],
1390 data["oil"],
1391 )
1392 assert (
1393 result is True
1394 ), "Testcase {} : Failed Error mroutes were flushed.".format(tc_name)
1395
1396 step(
1397 "After traffic stopped , verify (S,G) entries are flushed out"
1398 " from FRR1 node verify using 'show ip mroute' "
1399 )
1400
1401 input_dict = [
1402 {"dut": "l1", "src_address": source, "iif": "l1-r2-eth4", "oil": "l1-i1-eth1"},
1403 {"dut": "f1", "src_address": source, "iif": "i2-f1-eth0", "oil": "f1-r2-eth3"},
1404 ]
1405
1406 for data in input_dict:
1407 result = verify_ip_mroutes(
1408 tgen,
1409 data["dut"],
1410 data["src_address"],
1411 _IGMP_JOIN_RANGE,
1412 data["iif"],
1413 data["oil"],
1414 expected=False,
1415 )
1416 assert (
1417 result is not True
1418 ), "Testcase {} : Failed Error: \nmroutes are still present".format(tc_name)
1419
1420 write_test_footer(tc_name)
1421
1422
1423 def test_verify_mroute_when_5_different_receiver_joining_same_sources_p0(request):
1424 """
1425 TC_20: Verify mroute detail when 5 different receiver joining
1426 same source
1427 """
1428
1429 tgen = get_topogen()
1430 tc_name = request.node.name
1431 write_test_header(tc_name)
1432
1433 # Don"t run this test if we have any failure.
1434 if tgen.routers_have_failure():
1435 pytest.skip(tgen.errors)
1436
1437 # Creating configuration from JSON
1438 app_helper.stop_all_hosts()
1439 clear_ip_mroute(tgen)
1440 reset_config_on_routers(tgen)
1441 clear_ip_pim_interface_traffic(tgen, topo)
1442
1443 step("Configure static RP for (226.1.1.1-5) in c1")
1444 step("Configure static RP for (232.1.1.1-5) in c2")
1445
1446 _GROUP_RANGE = GROUP_RANGE_2 + GROUP_RANGE_3
1447 _IGMP_JOIN_RANGE = IGMP_JOIN_RANGE_2 + IGMP_JOIN_RANGE_3
1448
1449 input_dict = {
1450 "c1": {
1451 "pim": {
1452 "rp": [
1453 {
1454 "rp_addr": topo["routers"]["c1"]["links"]["lo"]["ipv4"].split(
1455 "/"
1456 )[0],
1457 "group_addr_range": GROUP_RANGE_2,
1458 }
1459 ]
1460 }
1461 },
1462 "c2": {
1463 "pim": {
1464 "rp": [
1465 {
1466 "rp_addr": topo["routers"]["c2"]["links"]["lo"]["ipv4"].split(
1467 "/"
1468 )[0],
1469 "group_addr_range": GROUP_RANGE_3,
1470 }
1471 ]
1472 }
1473 },
1474 }
1475
1476 result = create_pim_config(tgen, topo, input_dict)
1477 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1478
1479 step(
1480 "Configure 2 IGMP interface on FRR1 and send IGMP join"
1481 "for group (226.1.1.1-5, 232.1.1.1-5) from both the interface"
1482 )
1483 step(
1484 "Configure 2 IGMP interface on FRR3 and send IGMP join for"
1485 " group (226.1.1.1-5, 232.1.1.1-5) from both the interface"
1486 )
1487 step(
1488 "Configure 1 IGMP interface on c2 and send IGMP join for"
1489 "group (226.1.1.1-5, 232.1.1.1-5)"
1490 )
1491
1492 input_dict = {
1493 "f1": {
1494 "igmp": {
1495 "interfaces": {
1496 "f1-i8-eth2": {
1497 "igmp": {"version": "2", "query": {"query-interval": 15}}
1498 },
1499 "f1-i2-eth1": {
1500 "igmp": {"version": "2", "query": {"query-interval": 15}}
1501 },
1502 }
1503 }
1504 },
1505 "l1": {
1506 "igmp": {
1507 "interfaces": {
1508 "l1-i6-eth2": {
1509 "igmp": {"version": "2", "query": {"query-interval": 15}}
1510 }
1511 }
1512 }
1513 },
1514 }
1515 result = create_igmp_config(tgen, topo, input_dict)
1516 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1517
1518 input_join = {
1519 "i1": "i1-l1-eth0",
1520 "i6": "i6-l1-eth0",
1521 "i8": "i8-f1-eth0",
1522 "i2": "i2-f1-eth0",
1523 }
1524
1525 for recvr, recvr_intf in input_join.items():
1526 result = app_helper.run_join(recvr, _IGMP_JOIN_RANGE, join_intf=recvr_intf)
1527 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1528
1529 step("Configure one source in FRR2 , one in c1")
1530 step(
1531 "Send multicast traffic from both the sources to all the"
1532 "receivers (226.1.1.1-5, 232.1.1.1-5)"
1533 )
1534
1535 input_src = {"i3": "i3-r2-eth0"}
1536
1537 for src, src_intf in input_src.items():
1538 result = app_helper.run_traffic(src, _IGMP_JOIN_RANGE, bind_intf=src_intf)
1539 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1540 step(
1541 "After all the IGMP groups received with correct port using"
1542 " 'show ip igmp groups' in FRR1, FRR3, c2"
1543 )
1544 dut = "l1"
1545 interface = "l1-i6-eth2"
1546 result = verify_igmp_groups(tgen, dut, interface, _IGMP_JOIN_RANGE)
1547 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1548
1549 dut = "f1"
1550 interface = "f1-i8-eth2"
1551 result = verify_igmp_groups(tgen, dut, interface, _IGMP_JOIN_RANGE)
1552 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1553
1554 step(
1555 "(*,G) entries got created with upstream interface RP connected"
1556 " port using 'show ip pim upstream' in FRR1, FRR3, c2"
1557 )
1558 step(
1559 "(S,G) entries created for all the receiver after starting the"
1560 " source , traffic is reaching to all the receiver , verify OIL"
1561 " of (S,G) is receiver port using 'show ip mroute' in FRR1, "
1562 "FRR3 c2"
1563 )
1564
1565 source = topo["routers"]["i3"]["links"]["r2"]["ipv4"].split("/")[0]
1566 input_dict_all = [
1567 {
1568 "dut": "l1",
1569 "src_address": source,
1570 "iif": ["l1-r2-eth4", "l1-c1-eth0"],
1571 "oil": ["l1-i1-eth1", "l1-i6-eth2"],
1572 },
1573 {"dut": "f1", "src_address": source, "iif": "f1-r2-eth3", "oil": "f1-i8-eth2"},
1574 ]
1575 for data in input_dict_all:
1576 result = verify_ip_mroutes(
1577 tgen,
1578 data["dut"],
1579 data["src_address"],
1580 _IGMP_JOIN_RANGE,
1581 data["iif"],
1582 data["oil"],
1583 )
1584 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1585
1586 for data in input_dict_all:
1587 result = verify_upstream_iif(
1588 tgen, data["dut"], data["iif"], data["src_address"], _IGMP_JOIN_RANGE
1589 )
1590 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1591
1592 step("Shut the receiver interface one by one on FRR1 node")
1593 shutdown_bringup_interface(tgen, "l1", "l1-i1-eth1", False)
1594 shutdown_bringup_interface(tgen, "l1", "l1-i6-eth2", False)
1595
1596 step(
1597 "After shut the receiver port verify traffic is stopped immediately"
1598 " and (S,G) got timeout immediately in FRR1, FRR3, c2"
1599 )
1600 input_dict = [
1601 {"dut": "l1", "src_address": source, "iif": "l1-r2-eth4", "oil": "l1-i1-eth1"}
1602 ]
1603 for data in input_dict:
1604 result = verify_ip_mroutes(
1605 tgen,
1606 data["dut"],
1607 data["src_address"],
1608 IGMP_JOIN_RANGE_2,
1609 data["iif"],
1610 data["oil"],
1611 expected=False,
1612 )
1613 assert (
1614 result is not True
1615 ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
1616 tc_name, result
1617 )
1618 logger.info("Expected Behavior: {}".format(result))
1619
1620 step(
1621 "No traffic impact observed on other receivers verify using"
1622 " 'show ip mroute' "
1623 )
1624 input_dict = [
1625 {"dut": "f1", "src_address": source, "iif": "f1-r2-eth3", "oil": "f1-i8-eth2"}
1626 ]
1627 for data in input_dict:
1628 result = verify_ip_mroutes(
1629 tgen,
1630 data["dut"],
1631 data["src_address"],
1632 _IGMP_JOIN_RANGE,
1633 data["iif"],
1634 data["oil"],
1635 )
1636 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1637
1638 step("No shut the receiver interface one by one on FRR1 node")
1639 shutdown_bringup_interface(tgen, "l1", "l1-i1-eth1", True)
1640 shutdown_bringup_interface(tgen, "l1", "l1-i6-eth2", True)
1641
1642 step(
1643 "After no shut of receivers all the mroute entries got populated"
1644 ", no duplicate entries present in mroute"
1645 )
1646
1647 for data in input_dict_all:
1648 result = verify_ip_mroutes(
1649 tgen,
1650 data["dut"],
1651 data["src_address"],
1652 _IGMP_JOIN_RANGE,
1653 data["iif"],
1654 data["oil"],
1655 )
1656 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1657
1658 write_test_footer(tc_name)
1659
1660
1661 def test_verify_oil_iif_for_mroute_after_shut_noshut_source_interface_p1(request):
1662 """
1663 TC_22: Verify OIL and IIF detail updated in (S,G) mroute after shut
1664 and no shut of the source interface
1665 """
1666
1667 tgen = get_topogen()
1668 tc_name = request.node.name
1669 write_test_header(tc_name)
1670
1671 # Don"t run this test if we have any failure.
1672 if tgen.routers_have_failure():
1673 pytest.skip(tgen.errors)
1674
1675 # Creating configuration from JSON
1676 app_helper.stop_all_hosts()
1677 clear_ip_mroute(tgen)
1678 reset_config_on_routers(tgen)
1679 clear_ip_pim_interface_traffic(tgen, topo)
1680
1681 step("Configure static RP for (226.1.1.1-5) in c1")
1682 step("Configure static RP for (232.1.1.1-5) in c2")
1683
1684 _GROUP_RANGE = GROUP_RANGE_2 + GROUP_RANGE_3
1685 _IGMP_JOIN_RANGE = IGMP_JOIN_RANGE_2 + IGMP_JOIN_RANGE_3
1686
1687 input_dict = {
1688 "c1": {
1689 "pim": {
1690 "rp": [
1691 {
1692 "rp_addr": topo["routers"]["c1"]["links"]["lo"]["ipv4"].split(
1693 "/"
1694 )[0],
1695 "group_addr_range": GROUP_RANGE_2,
1696 }
1697 ]
1698 }
1699 },
1700 "c2": {
1701 "pim": {
1702 "rp": [
1703 {
1704 "rp_addr": topo["routers"]["c2"]["links"]["lo"]["ipv4"].split(
1705 "/"
1706 )[0],
1707 "group_addr_range": GROUP_RANGE_3,
1708 }
1709 ]
1710 }
1711 },
1712 }
1713
1714 result = create_pim_config(tgen, topo, input_dict)
1715 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1716
1717 step(
1718 "Configure IGMP interface on FRR1 and FRR3 and send IGMP join"
1719 " for group (226.1.1.1-5, 232.1.1.1-5)"
1720 )
1721
1722 input_dict = {
1723 "f1": {
1724 "igmp": {
1725 "interfaces": {
1726 "f1-i8-eth2": {
1727 "igmp": {"version": "2", "query": {"query-interval": 15}}
1728 }
1729 }
1730 }
1731 }
1732 }
1733 result = create_igmp_config(tgen, topo, input_dict)
1734 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1735
1736 input_join = {"i1": "i1-l1-eth0", "i8": "i8-f1-eth0"}
1737
1738 for recvr, recvr_intf in input_join.items():
1739 result = app_helper.run_join(recvr, _IGMP_JOIN_RANGE, join_intf=recvr_intf)
1740 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1741
1742 step("Configure 1 source in FRR1 , 1 in FRR3")
1743 step(
1744 "Send multicast traffic from both the sources to all the "
1745 "receivers (226.1.1.1-5, 232.1.1.1-5)"
1746 )
1747
1748 input_src = {"i6": "i6-l1-eth0", "i2": "i2-f1-eth0"}
1749
1750 for src, src_intf in input_src.items():
1751 result = app_helper.run_traffic(src, _IGMP_JOIN_RANGE, bind_intf=src_intf)
1752 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1753
1754 step(
1755 "*,G) is created and (S,G) created on FRR1 and FRR3 for both"
1756 " the source verify using 'show ip mroute' and "
1757 " 'show ip pim upstream' to check the upstream interface"
1758 " details"
1759 )
1760
1761 source_i6 = topo["routers"]["i6"]["links"]["l1"]["ipv4"].split("/")[0]
1762 source_i2 = topo["routers"]["i2"]["links"]["f1"]["ipv4"].split("/")[0]
1763 input_dict_all = [
1764 {"dut": "l1", "src_address": "*", "iif": "l1-c1-eth0", "oil": "l1-i1-eth1"},
1765 {
1766 "dut": "l1",
1767 "src_address": source_i2,
1768 "iif": "l1-r2-eth4",
1769 "oil": "l1-i1-eth1",
1770 },
1771 {
1772 "dut": "l1",
1773 "src_address": source_i6,
1774 "iif": "l1-i6-eth2",
1775 "oil": "l1-i1-eth1",
1776 },
1777 {"dut": "f1", "src_address": "*", "iif": "f1-c2-eth0", "oil": "f1-i8-eth2"},
1778 {
1779 "dut": "f1",
1780 "src_address": source_i2,
1781 "iif": "f1-i2-eth1",
1782 "oil": "f1-i8-eth2",
1783 },
1784 {
1785 "dut": "f1",
1786 "src_address": source_i6,
1787 "iif": "f1-r2-eth3",
1788 "oil": "f1-i8-eth2",
1789 },
1790 ]
1791 for data in input_dict_all:
1792 result = verify_ip_mroutes(
1793 tgen,
1794 data["dut"],
1795 data["src_address"],
1796 _IGMP_JOIN_RANGE,
1797 data["iif"],
1798 data["oil"],
1799 )
1800 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1801
1802 for data in input_dict_all:
1803 result = verify_upstream_iif(
1804 tgen, data["dut"], data["iif"], data["src_address"], _IGMP_JOIN_RANGE
1805 )
1806 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1807
1808 step("Shut the source interface one by one on FRR1")
1809 shutdown_bringup_interface(tgen, "f1", "f1-i2-eth1", False)
1810
1811 step(
1812 "After shut of ource interface from FRR3 verify all the (S,G) "
1813 "entries flushed out from FRR3 node 'show ip pim upstream' "
1814 " 'show ip mroute' "
1815 )
1816
1817 result = verify_ip_mroutes(
1818 tgen,
1819 "f1",
1820 source_i2,
1821 _IGMP_JOIN_RANGE,
1822 "f1-i2-eth1",
1823 "f1-i8-eth2",
1824 expected=False,
1825 )
1826 assert (
1827 result is not True
1828 ), "Testcase {} : Failed \n mroutes are" " still present \n Error: {}".format(
1829 tc_name, result
1830 )
1831 logger.info("Expected Behavior: {}".format(result))
1832
1833 result = verify_upstream_iif(
1834 tgen, "f1", "Unknown", "10.0.5.2", _IGMP_JOIN_RANGE, joinState="NotJoined"
1835 )
1836 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1837
1838 write_test_footer(tc_name)
1839
1840
1841 if __name__ == "__main__":
1842 args = ["-s"] + sys.argv[1:]
1843 sys.exit(pytest.main(args))