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