]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm1.py
Merge pull request #13183 from Pdoijode/pdoijode/pim-json-changes
[mirror_frr.git] / tests / topotests / multicast_pim6_sm_topo1 / test_multicast_pim6_sm1.py
CommitLineData
7ce53cf7
KK
1#!/usr/bin/env python
2# SPDX-License-Identifier: ISC
3
4#
5# Copyright (c) 2022 by VMware, Inc. ("VMware")
6# Used Copyright (c) 2018 by Network Device Education Foundation,
7# Inc. ("NetDEF") in this file.
8#
9
10"""
11Following tests are covered to test multicast pim6 sm:
12
13Test steps
14- Create topology (setup module)
15- Bring up topology
16
17Following tests are covered:
181. Verify Multicast data traffic with static RP, (*,g) and
19(s,g) OIL updated correctly
202. Verify mroute detail when receiver is present
21outside of FRR
223. Verify (*,G) and (S,G) populated correctly
23when FRR is the transit router
244. Verify (S,G) should not create if RP is not reachable
255. Verify modification of mld query timer should get update
26accordingly
276. Verify modification of mld max query response timer
28should get update accordingly
297. Verify removing the RP should not impact the multicast
30data traffic
31"""
32
33import os
34import sys
35import json
36import time
37import datetime
38import pytest
39
40# Save the Current Working Directory to find configuration files.
41CWD = os.path.dirname(os.path.realpath(__file__))
42sys.path.append(os.path.join(CWD, "../"))
43sys.path.append(os.path.join(CWD, "../lib/"))
44
45# Required to instantiate the topology builder class.
46
47# pylint: disable=C0413
48# Import topogen and topotest helpers
49from lib.topogen import Topogen, get_topogen
50
51from lib.common_config import (
52 start_topology,
53 write_test_header,
54 write_test_footer,
55 step,
56 reset_config_on_routers,
57 shutdown_bringup_interface,
58 start_router,
59 stop_router,
60 create_static_routes,
61 required_linux_kernel_version,
62 socat_send_mld_join,
63 socat_send_pim6_traffic,
64 get_frr_ipv6_linklocal,
0d58ebc4 65 kill_socat,
7ce53cf7
KK
66)
67from lib.bgp import create_router_bgp
68from lib.pim import (
69 create_pim_config,
70 create_mld_config,
71 verify_mld_groups,
72 verify_mroutes,
73 clear_pim6_interface_traffic,
74 verify_upstream_iif,
75 clear_pim6_mroute,
76 verify_pim_interface_traffic,
77 verify_pim_state,
78 McastTesterHelper,
79 verify_pim_join,
80 verify_mroute_summary,
81 verify_pim_nexthop,
82 verify_sg_traffic,
83 verify_mld_config,
84)
85
86from lib.topolog import logger
87from lib.topojson import build_config_from_json
88
89# Global variables
90GROUP_RANGE = "ff00::/8"
91
92GROUP_RANGE_1 = [
93 "ffaa::1/128",
94 "ffaa::2/128",
95 "ffaa::3/128",
96 "ffaa::4/128",
97 "ffaa::5/128",
98]
99MLD_JOIN_RANGE_1 = ["ffaa::1", "ffaa::2", "ffaa::3", "ffaa::4", "ffaa::5"]
100
101GROUP_RANGE_2 = [
102 "ffbb::1/128",
103 "ffbb::2/128",
104 "ffbb::3/128",
105 "ffbb::4/128",
106 "ffbb::5/128",
107]
108MLD_JOIN_RANGE_2 = ["ffbb::1", "ffbb::2", "ffbb::3", "ffbb::4", "ffbb::5"]
109GROUP_RANGE_3 = [
110 "ffcc::1/128",
111 "ffcc::2/128",
112 "ffcc::3/128",
113 "ffcc::4/128",
114 "ffcc::5/128",
115]
116MLD_JOIN_RANGE_3 = ["ffcc::1", "ffcc::2", "ffcc::3", "ffcc::4", "ffcc::5"]
117
118HELLO_TIMER = 1
119HOLD_TIMER = 3
120PREFERRED_NEXT_HOP = "link_local"
121ASSERT_MSG = "Testcase {} : Failed Error: {}"
122
123pytestmark = [pytest.mark.pim6d]
124
125
126def setup_module(mod):
127 """
128 Sets up the pytest environment
129
130 * `mod`: module name
131 """
132
133 # Required linux kernel version for this suite to run.
134 result = required_linux_kernel_version("4.19")
135 if result is not True:
136 pytest.skip("Kernel requirements are not met")
137
138 testsuite_run_time = time.asctime(time.localtime(time.time()))
139 logger.info("Testsuite start time: {}".format(testsuite_run_time))
140 logger.info("=" * 40)
141
142 logger.info("Running setup_module to create topology")
143
144 testdir = os.path.dirname(os.path.realpath(__file__))
145 json_file = "{}/multicast_pim6_sm_topo1.json".format(testdir)
146 tgen = Topogen(json_file, mod.__name__)
147 global topo
148 topo = tgen.json_topo
149 # ... and here it calls Mininet initialization functions.
150
151 # Starting topology, create tmp files which are loaded to routers
152 # to start deamons and then start routers
153 start_topology(tgen)
154
155 # Don"t run this test if we have any failure.
156 if tgen.routers_have_failure():
157 pytest.skip(tgen.errors)
158
159 # Creating configuration from JSON
160 build_config_from_json(tgen, tgen.json_topo)
161
7ce53cf7
KK
162 logger.info("Running setup_module() done")
163
164
165def teardown_module():
166 """Teardown the pytest environment"""
167
168 logger.info("Running teardown_module to delete topology")
169
170 tgen = get_topogen()
171
0d58ebc4
KK
172 # Clean up socat
173 kill_socat(tgen)
7ce53cf7
KK
174
175 # Stop toplogy and Remove tmp files
176 tgen.stop_topology()
177
178 logger.info(
179 "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
180 )
181 logger.info("=" * 40)
182
183
184#####################################################
185#
186# Local APIs
187#
188#####################################################
189
190
191def verify_mroute_repopulated(uptime_before, uptime_after):
192 """
193 API to compare uptime for mroutes
194
195 Parameters
196 ----------
197 * `uptime_before` : Uptime dictionary for any particular instance
198 * `uptime_after` : Uptime dictionary for any particular instance
199 """
200
201 for group in uptime_before.keys():
202 for source in uptime_before[group].keys():
203 if set(uptime_before[group]) != set(uptime_after[group]):
204 errormsg = (
205 "mroute (%s, %s) has not come"
206 " up after mroute clear [FAILED!!]" % (source, group)
207 )
208 return errormsg
209
210 d1 = datetime.datetime.strptime(uptime_before[group][source], "%H:%M:%S")
211 d2 = datetime.datetime.strptime(uptime_after[group][source], "%H:%M:%S")
212 if d2 >= d1:
213 errormsg = "mroute (%s, %s) is not " "repopulated [FAILED!!]" % (
214 source,
215 group,
216 )
217 return errormsg
218
219 logger.info("mroute (%s, %s) is " "repopulated [PASSED!!]", source, group)
220
221 return True
222
223
224def verify_state_incremented(state_before, state_after):
225 """
226 API to compare interface traffic state incrementing
227
228 Parameters
229 ----------
230 * `state_before` : State dictionary for any particular instance
231 * `state_after` : State dictionary for any particular instance
232 """
233
234 for router, state_data in state_before.items():
235 for state, value in state_data.items():
236 if state_before[router][state] >= state_after[router][state]:
237 errormsg = (
238 "[DUT: %s]: state %s value has not"
239 " incremented, Initial value: %s, "
240 "Current value: %s [FAILED!!]"
241 % (
242 router,
243 state,
244 state_before[router][state],
245 state_after[router][state],
246 )
247 )
248 return errormsg
249
250 logger.info(
251 "[DUT: %s]: State %s value is "
252 "incremented, Initial value: %s, Current value: %s"
253 " [PASSED!!]",
254 router,
255 state,
256 state_before[router][state],
257 state_after[router][state],
258 )
259
260 return True
261
262
263def next_hop_per_address_family(
264 tgen, dut, peer, addr_type, next_hop_dict, preferred_next_hop=PREFERRED_NEXT_HOP
265):
266 """
267 This function returns link_local or global next_hop per address-family
268 """
269
270 intferface = topo["routers"][peer]["links"]["{}".format(dut)]["interface"]
271 if addr_type == "ipv6" and "link_local" in preferred_next_hop:
272 next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
273 else:
274 next_hop = next_hop_dict[addr_type]
275
276 return next_hop
277
278
279#####################################################
280#
281# Testcases
282#
283#####################################################
284
285
286def test_multicast_data_traffic_static_RP_send_traffic_then_join_p0(request):
287 """
288 Verify Multicast data traffic with static RP, (*,g) and
289 (s,g) OIL updated correctly
290 """
291
292 tgen = get_topogen()
293 tc_name = request.node.name
294 write_test_header(tc_name)
295
296 # Creating configuration from JSON
297 reset_config_on_routers(tgen)
298
299 # Don"t run this test if we have any failure.
300 if tgen.routers_have_failure():
301 pytest.skip(tgen.errors)
302
303 logger.info("shut R1 to R4 and R3 to R5 link to simulate test topology")
304 r1_r4 = topo["routers"]["r1"]["links"]["r4"]["interface"]
305 r3_r5 = topo["routers"]["r3"]["links"]["r5"]["interface"]
306
307 shutdown_bringup_interface(tgen, "r1", r1_r4, False)
308 shutdown_bringup_interface(tgen, "r3", r3_r5, False)
309
310 step(
311 "Configure RP as R2 (loopback interface) for the"
312 " group range ff00::/8 on all the routers"
313 )
314
315 input_dict = {
316 "r2": {
317 "pim6": {
318 "rp": [
319 {
320 "rp_addr": topo["routers"]["r2"]["links"]["lo"]["ipv6"].split(
321 "/"
322 )[0],
323 "group_addr_range": GROUP_RANGE,
324 }
325 ]
326 }
327 }
328 }
329
330 result = create_pim_config(tgen, topo, input_dict)
331 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
332
333 step("Start traffic first and then send the mld join")
334
335 step("Send multicast traffic from FRR3 to all the receivers" "ffaa::1-5")
336
337 intf_ip = topo["routers"]["i2"]["links"]["r3"]["ipv6"].split("/")[0]
338 intf = topo["routers"]["i2"]["links"]["r3"]["interface"]
339 result = socat_send_pim6_traffic(tgen, "i2", "UDP6-SEND", MLD_JOIN_RANGE_1, intf)
340 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
341
342 source = topo["routers"]["i2"]["links"]["r3"]["ipv6"].split("/")[0]
343
344 step("verify upstream in NOT join Rej prune state on R3")
345
346 input_dict_sg = [
347 {
348 "dut": "r3",
349 "src_address": source,
350 "iif": topo["routers"]["r3"]["links"]["i2"]["interface"],
351 "oil": topo["routers"]["r3"]["links"]["r2"]["interface"],
352 }
353 ]
354
355 for data in input_dict_sg:
356 result = verify_upstream_iif(
357 tgen,
358 data["dut"],
359 data["iif"],
360 data["src_address"],
361 MLD_JOIN_RANGE_1,
362 joinState="NotJoined",
363 regState="RegPrune",
364 )
365 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
366
367 step("joinRx value before join sent")
368 r2_r1_intf = topo["routers"]["r2"]["links"]["r1"]["interface"]
369 state_dict = {"r2": {r2_r1_intf: ["joinRx"]}}
370 state_before = verify_pim_interface_traffic(tgen, state_dict, addr_type="ipv6")
371 assert isinstance(
372 state_before, dict
373 ), "Testcase {} : Failed \n state_before is not dictionary \n " "Error: {}".format(
374 tc_name, result
375 )
376
377 step("send mld join (ffaa::1-5) to R1")
378 intf = topo["routers"]["i1"]["links"]["r1"]["interface"]
379 intf_ip = topo["routers"]["i1"]["links"]["r1"]["ipv6"].split("/")[0]
380 result = socat_send_mld_join(
381 tgen, "i1", "UDP6-RECV", MLD_JOIN_RANGE_1, intf, intf_ip
382 )
383 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
384
385 step(
386 "Verify 'show ipv6 mroute' showing correct RPF and OIF"
387 " interface for (*,G) and (S,G) entries on all the nodes"
388 )
389
390 input_dict = [
391 {
392 "dut": "r1",
393 "src_address": "*",
394 "iif": topo["routers"]["r1"]["links"]["r2"]["interface"],
395 "oil": topo["routers"]["r1"]["links"]["i1"]["interface"],
396 },
397 {
398 "dut": "r1",
399 "src_address": source,
400 "iif": topo["routers"]["r1"]["links"]["r2"]["interface"],
401 "oil": topo["routers"]["r1"]["links"]["i1"]["interface"],
402 },
403 {
404 "dut": "r2",
405 "src_address": "*",
406 "iif": "lo",
407 "oil": topo["routers"]["r2"]["links"]["r1"]["interface"],
408 },
409 {
410 "dut": "r2",
411 "src_address": source,
412 "iif": topo["routers"]["r2"]["links"]["r3"]["interface"],
413 "oil": topo["routers"]["r2"]["links"]["r1"]["interface"],
414 },
415 {
416 "dut": "r3",
417 "src_address": source,
418 "iif": topo["routers"]["r3"]["links"]["i2"]["interface"],
419 "oil": topo["routers"]["r3"]["links"]["r2"]["interface"],
420 },
421 ]
422
423 for data in input_dict:
424 result = verify_mroutes(
425 tgen,
426 data["dut"],
427 data["src_address"],
428 MLD_JOIN_RANGE_1,
429 data["iif"],
430 data["oil"],
431 )
432 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
433
434 step(
435 "Verify 'show ipv6 pim upstream' showing correct OIL and IIF"
436 " on all the nodes"
437 )
438 for data in input_dict:
439 result = verify_upstream_iif(
440 tgen, data["dut"], data["iif"], data["src_address"], MLD_JOIN_RANGE_1
441 )
442 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
443
444 step("verify join state is joined")
445 for data in input_dict_sg:
446 result = verify_upstream_iif(
447 tgen,
448 data["dut"],
449 data["iif"],
450 data["src_address"],
451 MLD_JOIN_RANGE_1,
452 joinState="Joined",
453 regState="RegPrune",
454 )
455 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
456
457 step("joinRx value after join sent")
458 state_after = verify_pim_interface_traffic(tgen, state_dict, addr_type="ipv6")
459 assert isinstance(
460 state_after, dict
461 ), "Testcase {} : Failed \n state_before is not dictionary \n " "Error: {}".format(
462 tc_name, result
463 )
464
465 step(
466 "r1 sent PIM (*,G) join to r2 verify using"
467 "'show ipv6 pim interface traffic' on RP connected interface"
468 )
469
470 result = verify_state_incremented(state_before, state_after)
471 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
472
473 step("r1 sent PIM (S,G) join to r3 , verify using 'show ipv6 pim join'")
474 dut = "r3"
475 interface = topo["routers"]["r3"]["links"]["r2"]["interface"]
476 result = verify_pim_join(tgen, topo, dut, interface, MLD_JOIN_RANGE_1)
477 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
478
479 _nexthop = topo["routers"]["r1"]["links"]["r2"]["ipv6"].split("/")[0]
480 next_hop = next_hop_per_address_family(tgen, "r1", "r2", "ipv6", _nexthop)
481
482 step("verify nexthop on r3 using 'show ipv6 pim nexthop'")
483 result = verify_pim_nexthop(tgen, topo, "r1", next_hop, "ipv6")
484 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
485
486 step("verify mroute summary on r1 using 'show ipv6 mroute summary json'")
487 result = verify_mroute_summary(
488 tgen, "r1", sg_mroute=5, starg_mroute=5, total_mroute=10, addr_type="ipv6"
489 )
490 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
491
492 write_test_footer(tc_name)
493
494
495def test_verify_mroute_when_receiver_is_outside_frr_p0(request):
496 """
497 Verify mroute detail when receiver is present
498 outside of FRR
499 """
500 tgen = get_topogen()
501 tc_name = request.node.name
502 write_test_header(tc_name)
503
504 # Creating configuration from JSON
505 reset_config_on_routers(tgen)
506
507 # Don"t run this test if we have any failure.
508 if tgen.routers_have_failure():
509 pytest.skip(tgen.errors)
510
511 step("Configure static RP on r4 for group range " "(ffcc::1-5) and (ffbb::1-5)")
512
513 _GROUP_RANGE = GROUP_RANGE_2 + GROUP_RANGE_3
514 _MLD_JOIN_RANGE = MLD_JOIN_RANGE_2 + MLD_JOIN_RANGE_3
515
516 input_dict = {
517 "r4": {
518 "pim6": {
519 "rp": [
520 {
521 "rp_addr": topo["routers"]["r4"]["links"]["lo"]["ipv6"].split(
522 "/"
523 )[0],
524 "group_addr_range": _GROUP_RANGE,
525 }
526 ]
527 }
528 }
529 }
530
531 result = create_pim_config(tgen, topo, input_dict)
532 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
533
534 step("send mld join (ffaa::1-5) to R1")
535 intf = topo["routers"]["i1"]["links"]["r1"]["interface"]
536 intf_ip = topo["routers"]["i1"]["links"]["r1"]["ipv6"].split("/")[0]
537 result = socat_send_mld_join(
538 tgen, "i1", "UDP6-RECV", _MLD_JOIN_RANGE, intf, intf_ip
539 )
540 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
541
542 step("verify MLD joins received on r1")
543 dut = "r1"
544 interface = topo["routers"]["r1"]["links"]["i1"]["interface"]
545 result = verify_mld_groups(tgen, dut, interface, _MLD_JOIN_RANGE)
546 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
547
548 step("Send multicast traffic from FRR3 to all the receivers" "ffaa::1-5")
549 intf_ip = topo["routers"]["i2"]["links"]["r3"]["ipv6"].split("/")[0]
550 intf = topo["routers"]["i2"]["links"]["r3"]["interface"]
551 result = socat_send_pim6_traffic(tgen, "i2", "UDP6-SEND", _MLD_JOIN_RANGE, intf)
552 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
553
554 step(
555 "Configure one more receiver in r5 enable mld and send"
556 " join (ffaa::1-5) and (ffbb::1-5)"
557 )
558 r5_i5 = topo["routers"]["r5"]["links"]["i5"]["interface"]
559
560 input_dict = {"r5": {"mld": {"interfaces": {r5_i5: {"mld": {"version": "1"}}}}}}
561 result = create_mld_config(tgen, topo, input_dict)
562 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
563
564 i5_r5 = topo["routers"]["i5"]["links"]["r5"]["interface"]
565 intf_ip = topo["routers"]["i5"]["links"]["r5"]["ipv6"].split("/")[0]
566 result = socat_send_mld_join(
567 tgen, "i5", "UDP6-RECV", _MLD_JOIN_RANGE, i5_r5, intf_ip
568 )
569 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
570
571 step("FRR1 has 10 (*.G) and 10 (S,G) verify using 'show ipv6 mroute'")
572 step(
573 "All the receiver are receiving traffic on FRR1 and (S,G) OIL is towards"
574 "receivers, verify using 'show mroute' 'show pim upstream'"
575 )
576 step(
577 "All the receiver are receiving traffic on r5 and (S,G) OIL is "
578 "toward receivers, verify using 'show ipv6 mroute' 'show ipv6 pim upstream'"
579 )
580
581 source = topo["routers"]["i2"]["links"]["r3"]["ipv6"].split("/")[0]
582 input_dict = [
583 {
584 "dut": "r1",
585 "src_address": "*",
586 "iif": topo["routers"]["r1"]["links"]["r4"]["interface"],
587 "oil": topo["routers"]["r1"]["links"]["i1"]["interface"],
588 },
589 {
590 "dut": "r1",
591 "src_address": source,
592 "iif": topo["routers"]["r1"]["links"]["r2"]["interface"],
593 "oil": topo["routers"]["r1"]["links"]["i1"]["interface"],
594 },
595 {
596 "dut": "r5",
597 "src_address": "*",
598 "iif": topo["routers"]["r5"]["links"]["r4"]["interface"],
599 "oil": topo["routers"]["r5"]["links"]["i5"]["interface"],
600 },
601 {
602 "dut": "r5",
603 "src_address": source,
604 "iif": topo["routers"]["r5"]["links"]["r3"]["interface"],
605 "oil": topo["routers"]["r5"]["links"]["i5"]["interface"],
606 },
607 ]
608
609 for data in input_dict:
610 result = verify_mroutes(
611 tgen,
612 data["dut"],
613 data["src_address"],
614 _MLD_JOIN_RANGE,
615 data["iif"],
616 data["oil"],
617 )
618 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
619
620 step(
621 "FRR3 has (S,G) OIL created toward r2/r5 receiver and FRR1 receiver"
622 "'show ipv6 pim '"
623 )
624 input_dict = [
625 {
626 "dut": "r3",
627 "src_address": source,
628 "iif": topo["routers"]["r3"]["links"]["i2"]["interface"],
629 "oil": topo["routers"]["r3"]["links"]["r5"]["interface"],
630 },
631 {
632 "dut": "r3",
633 "src_address": source,
634 "iif": topo["routers"]["r3"]["links"]["i2"]["interface"],
635 "oil": topo["routers"]["r3"]["links"]["r2"]["interface"],
636 },
637 ]
638 for data in input_dict:
639 result = verify_pim_state(
640 tgen,
641 data["dut"],
642 data["iif"],
643 data["oil"],
644 _MLD_JOIN_RANGE,
645 data["src_address"],
646 )
647 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
648
649 for data in input_dict:
650 result = verify_upstream_iif(
651 tgen,
652 data["dut"],
653 data["iif"],
654 data["src_address"],
655 _MLD_JOIN_RANGE,
656 joinState="Joined",
657 regState="RegPrune",
658 )
659 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
660
661 step("Traffic is received fine on FRR1 and r5 " " 'show ipv6 mroute count' ")
662
663 result = verify_sg_traffic(tgen, "r1", _MLD_JOIN_RANGE, source, "ipv6")
664 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
665
666 result = verify_sg_traffic(tgen, "r5", _MLD_JOIN_RANGE, source, "ipv6")
667 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
668
669 write_test_footer(tc_name)
670
671
672def test_verify_mroute_when_frr_is_transit_router_p2(request):
673 """
674 Verify (*,G) and (S,G) populated correctly
675 when FRR is the transit router
676 """
677
678 tgen = get_topogen()
679 tc_name = request.node.name
680 write_test_header(tc_name)
681
682 # Creating configuration from JSON
683 reset_config_on_routers(tgen)
684
685 # Don"t run this test if we have any failure.
686 if tgen.routers_have_failure():
687 pytest.skip(tgen.errors)
688
689 step("Configure static RP for (ffaa::1-5) in r5")
690 input_dict = {
691 "r5": {
692 "pim6": {
693 "rp": [
694 {
695 "rp_addr": topo["routers"]["r5"]["links"]["lo"]["ipv6"].split(
696 "/"
697 )[0],
698 "group_addr_range": GROUP_RANGE_1,
699 }
700 ]
701 }
702 }
703 }
704
705 result = create_pim_config(tgen, topo, input_dict)
706 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
707
708 step("Enable mld on FRR1 interface and send mld join ")
709
710 step("send mld join (ffaa::1-5) to R1")
711 intf = topo["routers"]["i1"]["links"]["r1"]["interface"]
712 intf_ip = topo["routers"]["i1"]["links"]["r1"]["ipv6"].split("/")[0]
713 result = socat_send_mld_join(
714 tgen, "i1", "UDP6-RECV", MLD_JOIN_RANGE_1, intf, intf_ip
715 )
716 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
717
718 step("verify mld groups received on R1")
719 dut = "r1"
720 interface = topo["routers"]["r1"]["links"]["i1"]["interface"]
721 result = verify_mld_groups(tgen, dut, interface, MLD_JOIN_RANGE_1)
722 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
723
724 step("Send multicast traffic from FRR3 to ffaa::1-5 receivers")
725 intf_ip = topo["routers"]["i2"]["links"]["r3"]["ipv6"].split("/")[0]
726 intf = topo["routers"]["i2"]["links"]["r3"]["interface"]
727 result = socat_send_pim6_traffic(tgen, "i2", "UDP6-SEND", MLD_JOIN_RANGE_1, intf)
728 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
729
730 step("shut the direct link to R1 ")
731 intf = topo["routers"]["r1"]["links"]["r2"]["interface"]
732 shutdown_bringup_interface(tgen, dut, intf, False)
733
734 step(
735 "FRR4 has (S,G) and (*,G) ,created where incoming interface"
736 " toward FRR3 and OIL toward R2, verify using 'show ipv6 mroute'"
737 " 'show ipv6 pim state' "
738 )
739
740 source = topo["routers"]["i2"]["links"]["r3"]["ipv6"].split("/")[0]
741 input_dict = [
742 {
743 "dut": "r5",
744 "src_address": "*",
745 "iif": "lo",
746 "oil": topo["routers"]["r5"]["links"]["r4"]["interface"],
747 },
748 {
749 "dut": "r5",
750 "src_address": source,
751 "iif": topo["routers"]["r5"]["links"]["r3"]["interface"],
752 "oil": topo["routers"]["r5"]["links"]["r4"]["interface"],
753 },
754 ]
755 for data in input_dict:
756 result = verify_mroutes(
757 tgen,
758 data["dut"],
759 data["src_address"],
760 MLD_JOIN_RANGE_1,
761 data["iif"],
762 data["oil"],
763 )
764 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
765
766 step("verify multicast traffic")
767 result = verify_sg_traffic(tgen, "r5", MLD_JOIN_RANGE_1, source, "ipv6")
768 assert (
769 result is True
770 ), "Testcase {} : Failed \n mroutes traffic " "still present \n Error: {}".format(
771 tc_name, result
772 )
773
774 step("Stop multicast traffic from FRR3")
775 dut = "i2"
776 intf = topo["routers"]["i2"]["links"]["r3"]["interface"]
777 shutdown_bringup_interface(tgen, dut, intf, False)
778
779 step("(*,G) present on R5 after source shut")
780
781 input_dict_1 = [
782 {
783 "dut": "r5",
784 "src_address": "*",
785 "iif": "lo",
786 "oil": topo["routers"]["r5"]["links"]["r4"]["interface"],
787 },
788 ]
789 for data in input_dict_1:
790 result = verify_mroutes(
791 tgen,
792 data["dut"],
793 data["src_address"],
794 MLD_JOIN_RANGE_1,
795 data["iif"],
796 data["oil"],
797 )
798 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
799
800 step("stop mld receiver from FRR1")
801 dut = "i1"
802 intf = topo["routers"]["i1"]["links"]["r1"]["interface"]
803 shutdown_bringup_interface(tgen, dut, intf, False)
804
805 step(
806 "After stopping receiver (*, G) and (S, G) also got removed from transit"
807 " router 'show ipv6 mroute'"
808 )
809
810 for data in input_dict:
811 result = verify_mroutes(
812 tgen,
813 data["dut"],
814 data["src_address"],
815 MLD_JOIN_RANGE_1,
816 data["iif"],
817 data["oil"],
818 expected=False,
819 )
820 assert result is not True, (
821 "Testcase {} : Failed \n mroutes "
822 "not removed after removing the receivers \n Error: {}".format(
823 tc_name, result
824 )
825 )
826
827 logger.info("Expected Behavior: {}".format(result))
828
829 write_test_footer(tc_name)
830
831
832def test_verify_mroute_when_RP_unreachable_p1(request):
833 """
834 Verify (S,G) should not create if RP is not reachable
835 """
836
837 tgen = get_topogen()
838 tc_name = request.node.name
839 write_test_header(tc_name)
840
841 # Creating configuration from JSON
842 reset_config_on_routers(tgen)
843
844 # Don"t run this test if we have any failure.
845 if tgen.routers_have_failure():
846 pytest.skip(tgen.errors)
847
848 step("Configure RP on FRR2 (loopback interface) for " "the group range ffaa::1-5")
849
850 input_dict = {
851 "r2": {
852 "pim6": {
853 "rp": [
854 {
855 "rp_addr": topo["routers"]["r2"]["links"]["lo"]["ipv6"].split(
856 "/"
857 )[0],
858 "group_addr_range": GROUP_RANGE_1,
859 }
860 ]
861 }
862 }
863 }
864
865 result = create_pim_config(tgen, topo, input_dict)
866 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
867
868 step("Enable mld on FRR1 interface and send mld join ffaa::1-5")
869
870 step("send mld join (ffaa::1-5) to R1")
871 intf = topo["routers"]["i1"]["links"]["r1"]["interface"]
872 intf_ip = topo["routers"]["i1"]["links"]["r1"]["ipv6"].split("/")[0]
873 result = socat_send_mld_join(
874 tgen, "i1", "UDP6-RECV", MLD_JOIN_RANGE_1, intf, intf_ip
875 )
876 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
877
878 step("Send multicast traffic from FRR3 to ffaa::1-5 receivers")
879 intf_ip = topo["routers"]["i2"]["links"]["r3"]["ipv6"].split("/")[0]
880 intf = topo["routers"]["i2"]["links"]["r3"]["interface"]
881 result = socat_send_pim6_traffic(tgen, "i2", "UDP6-SEND", MLD_JOIN_RANGE_1, intf)
882 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
883
884 step("Configure one MLD interface on FRR3 node and send MLD" " join (ffcc::1)")
885 r3_i8 = topo["routers"]["r3"]["links"]["i8"]["interface"]
886 input_dict = {"r3": {"mld": {"interfaces": {r3_i8: {"mld": {"version": "1"}}}}}}
887 result = create_mld_config(tgen, topo, input_dict)
888 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
889
890 step("send mld join (ffaa::1-5) to R1")
891 intf = topo["routers"]["i8"]["links"]["r3"]["interface"]
892 intf_ip = topo["routers"]["i8"]["links"]["r3"]["ipv6"].split("/")[0]
893 result = socat_send_mld_join(
894 tgen, "i8", "UDP6-RECV", MLD_JOIN_RANGE_1, intf, intf_ip
895 )
896 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
897
898 step("verify MLD groups received ")
899 dut = "r3"
900 interface = topo["routers"]["r3"]["links"]["i8"]["interface"]
901 result = verify_mld_groups(tgen, dut, interface, MLD_JOIN_RANGE_1)
902 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
903
904 source = topo["routers"]["i2"]["links"]["r3"]["ipv6"].split("/")[0]
905 input_dict = [
906 {
907 "dut": "r3",
908 "src_address": "*",
909 "iif": topo["routers"]["r3"]["links"]["r2"]["interface"],
910 "oil": topo["routers"]["r3"]["links"]["i8"]["interface"],
911 },
912 {
913 "dut": "r3",
914 "src_address": source,
915 "iif": topo["routers"]["r3"]["links"]["i2"]["interface"],
916 "oil": topo["routers"]["r3"]["links"]["i8"]["interface"],
917 },
918 ]
919 for data in input_dict:
920 result = verify_mroutes(
921 tgen,
922 data["dut"],
923 data["src_address"],
924 MLD_JOIN_RANGE_1,
925 data["iif"],
926 data["oil"],
927 )
928 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
929
930 step("Shut the RP connected interface from r3 ( r2 to r3) link")
931 dut = "r3"
932 intf = topo["routers"]["r3"]["links"]["r2"]["interface"]
933 shutdown_bringup_interface(tgen, dut, intf, False)
934
935 step("Clear the mroute on r3")
936 clear_pim6_mroute(tgen, "r3")
937
938 step(
939 "After Shut the RP interface and clear the mroute verify all "
940 "(*,G) and (S,G) got timeout from FRR3 node , verify using "
941 " 'show ipv6 mroute' "
942 )
943 r3_r2 = topo["routers"]["r3"]["links"]["r2"]["interface"]
944 r3_i8 = topo["routers"]["r3"]["links"]["i8"]["interface"]
945
946 result = verify_mroutes(
947 tgen, "r3", "*", MLD_JOIN_RANGE_1, r3_r2, r3_i8, expected=False
948 )
949 assert (
950 result is not True
951 ), "Testcase {} : Failed \n mroutes are" " still present \n Error: {}".format(
952 tc_name, result
953 )
954 logger.info("Expected Behavior: {}".format(result))
955
956 step("mld groups are present verify using 'show ip mld group'")
957 dut = "r1"
958 interface = topo["routers"]["r1"]["links"]["i1"]["interface"]
959 result = verify_mld_groups(tgen, dut, interface, MLD_JOIN_RANGE_1)
960 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
961
962 write_test_footer(tc_name)
963
964
965def test_modify_mld_query_timer_p0(request):
966 """
967 Verify modification of mld query timer should get update
968 accordingly
969 """
970
971 tgen = get_topogen()
972 tc_name = request.node.name
973 write_test_header(tc_name)
974
975 # Creating configuration from JSON
976 reset_config_on_routers(tgen)
977
978 # Don"t run this test if we have any failure.
979 if tgen.routers_have_failure():
980 pytest.skip(tgen.errors)
981
982 step("send mld join (ffaa::1-5) to R1")
983 intf = topo["routers"]["i8"]["links"]["r3"]["interface"]
984 intf_ip = topo["routers"]["i8"]["links"]["r3"]["ipv6"].split("/")[0]
985 result = socat_send_mld_join(
986 tgen, "i8", "UDP6-RECV", MLD_JOIN_RANGE_1, intf, intf_ip
987 )
988 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
989
990 step("Enable MLD on receiver interface")
991 intf_r3_i8 = topo["routers"]["r3"]["links"]["i8"]["interface"]
992 input_dict_1 = {
993 "r3": {"mld": {"interfaces": {intf_r3_i8: {"mld": {"version": "1"}}}}}
994 }
995
996 result = create_mld_config(tgen, topo, input_dict_1)
997 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
998
999 step("verify MLD groups received ")
1000 dut = "r3"
1001 interface = topo["routers"]["r3"]["links"]["i8"]["interface"]
1002 result = verify_mld_groups(tgen, dut, interface, MLD_JOIN_RANGE_1)
1003 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1004
1005 step("Configure RP on R2 (loopback interface) for the" " group range ffaa::1-5")
1006
1007 input_dict = {
1008 "r2": {
1009 "pim6": {
1010 "rp": [
1011 {
1012 "rp_addr": topo["routers"]["r2"]["links"]["lo"]["ipv6"].split(
1013 "/"
1014 )[0],
1015 "group_addr_range": GROUP_RANGE_1,
1016 }
1017 ]
1018 }
1019 }
1020 }
1021
1022 result = create_pim_config(tgen, topo, input_dict)
1023 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1024
1025 step("Send multicast traffic from FRR3 to ffaa::1-5 receivers")
1026 intf_ip = topo["routers"]["i2"]["links"]["r3"]["ipv6"].split("/")[0]
1027 intf = topo["routers"]["i2"]["links"]["r3"]["interface"]
1028 result = socat_send_pim6_traffic(tgen, "i2", "UDP6-SEND", MLD_JOIN_RANGE_1, intf)
1029 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1030
1031 step(
1032 "Verify 'show ipv6 mroute' showing correct RPF and OIF"
1033 " interface for (*,G) and (S,G) entries on all the nodes"
1034 )
1035
1036 source = topo["routers"]["i2"]["links"]["r3"]["ipv6"].split("/")[0]
1037 input_dict_4 = [
1038 {
1039 "dut": "r3",
1040 "src_address": source,
1041 "iif": topo["routers"]["r3"]["links"]["i2"]["interface"],
1042 "oil": topo["routers"]["r3"]["links"]["i8"]["interface"],
1043 },
1044 {
1045 "dut": "r3",
1046 "src_address": "*",
1047 "iif": topo["routers"]["r3"]["links"]["r2"]["interface"],
1048 "oil": topo["routers"]["r3"]["links"]["i8"]["interface"],
1049 },
1050 ]
1051 for data in input_dict_4:
1052 result = verify_mroutes(
1053 tgen,
1054 data["dut"],
1055 data["src_address"],
1056 MLD_JOIN_RANGE_1,
1057 data["iif"],
1058 data["oil"],
1059 mwait=20,
1060 )
1061 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1062
1063 step(
1064 "Verify 'show ipv6 pim upstream' showing correct OIL and IIF"
1065 " on all the nodes"
1066 )
1067 for data in input_dict_4:
1068 result = verify_upstream_iif(
1069 tgen, data["dut"], data["iif"], data["src_address"], MLD_JOIN_RANGE_1
1070 )
1071 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1072
1073 step("Modify mld query interval default to other timer on FRR1" ", 3 times")
1074
1075 input_dict_1 = {
1076 "r3": {
1077 "mld": {
1078 "interfaces": {intf_r3_i8: {"mld": {"query": {"query-interval": 100}}}}
1079 }
1080 }
1081 }
1082 result = create_mld_config(tgen, topo, input_dict_1)
1083 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1084
1085 result = verify_mld_config(tgen, input_dict_1)
1086 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1087
1088 input_dict_2 = {
1089 "r3": {
1090 "mld": {
1091 "interfaces": {intf_r3_i8: {"mld": {"query": {"query-interval": 200}}}}
1092 }
1093 }
1094 }
1095 result = create_mld_config(tgen, topo, input_dict_2)
1096 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1097
1098 result = verify_mld_config(tgen, input_dict_2)
1099 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1100
1101 input_dict_3 = {
1102 "r3": {
1103 "mld": {
1104 "interfaces": {intf_r3_i8: {"mld": {"query": {"query-interval": 300}}}}
1105 }
1106 }
1107 }
1108 result = create_mld_config(tgen, topo, input_dict_3)
1109 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1110
1111 result = verify_mld_config(tgen, input_dict_3)
1112 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1113
1114 input_dict_3 = {
1115 "r3": {
1116 "mld": {
1117 "interfaces": {
1118 intf_r3_i8: {
1119 "mld": {"query": {"query-interval": 300, "delete": True}}
1120 }
1121 }
1122 }
1123 }
1124 }
1125 result = create_mld_config(tgen, topo, input_dict_3)
1126 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1127
1128 step("veriffy mroutes after query modification")
1129 for data in input_dict_4:
1130 result = verify_mroutes(
1131 tgen,
1132 data["dut"],
1133 data["src_address"],
1134 MLD_JOIN_RANGE_1,
1135 data["iif"],
1136 data["oil"],
1137 mwait=20,
1138 )
1139 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1140
1141 step("Verify that no core is observed")
1142 if tgen.routers_have_failure():
1143 assert False, "Testcase {}: Failed Error: {}".format(tc_name, result)
1144
1145 write_test_footer(tc_name)
1146
1147
1148def test_modify_mld_max_query_response_timer_p0(request):
1149 """
1150 Verify modification of mld max query response timer
1151 should get update accordingly
1152 """
1153
1154 tgen = get_topogen()
1155 tc_name = request.node.name
1156 write_test_header(tc_name)
1157
1158 # Creating configuration from JSON
1159 reset_config_on_routers(tgen)
1160
1161 # Don"t run this test if we have any failure.
1162 if tgen.routers_have_failure():
1163 pytest.skip(tgen.errors)
1164
1165 step("Enable mld on FRR1 interface and send MLD join")
1166 step("send mld join (ffaa::1-5) to R1")
1167 intf = topo["routers"]["i1"]["links"]["r1"]["interface"]
1168 intf_ip = topo["routers"]["i1"]["links"]["r1"]["ipv6"].split("/")[0]
1169 result = socat_send_mld_join(
1170 tgen, "i1", "UDP6-RECV", MLD_JOIN_RANGE_1, intf, intf_ip
1171 )
1172 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1173
1174 r1_i1 = topo["routers"]["r1"]["links"]["i1"]["interface"]
1175 step("Configure mld query response time to 10 sec on FRR1")
1176 input_dict_1 = {
1177 "r1": {
1178 "mld": {
1179 "interfaces": {
1180 r1_i1: {
1181 "mld": {
1182 "version": "1",
1183 "query": {"query-max-response-time": 10},
1184 }
1185 }
1186 }
1187 }
1188 }
1189 }
1190 result = create_mld_config(tgen, topo, input_dict_1)
1191 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1192
1193 result = verify_mld_config(tgen, input_dict_1)
1194 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1195
1196 step("Configure RP on R2 (loopback interface) for the" " group range 225.0.0.0/8")
1197
1198 input_dict = {
1199 "r2": {
1200 "pim6": {
1201 "rp": [
1202 {
1203 "rp_addr": topo["routers"]["r2"]["links"]["lo"]["ipv6"].split(
1204 "/"
1205 )[0],
1206 "group_addr_range": GROUP_RANGE_1,
1207 }
1208 ]
1209 }
1210 }
1211 }
1212
1213 result = create_pim_config(tgen, topo, input_dict)
1214 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1215
1216 step("Send multicast traffic from FRR3 to ffaa::1-5 receivers")
1217 intf_ip = topo["routers"]["i2"]["links"]["r3"]["ipv6"].split("/")[0]
1218 intf = topo["routers"]["i2"]["links"]["r3"]["interface"]
1219 result = socat_send_pim6_traffic(tgen, "i2", "UDP6-SEND", MLD_JOIN_RANGE_1, intf)
1220 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1221
1222 step(
1223 "Verify 'show ipv6 mroute' showing correct RPF and OIF"
1224 " interface for (*,G) and (S,G) entries on all the nodes"
1225 )
1226
1227 source = topo["routers"]["i2"]["links"]["r3"]["ipv6"].split("/")[0]
1228 input_dict_5 = [
1229 {
1230 "dut": "r1",
1231 "src_address": "*",
1232 "iif": topo["routers"]["r1"]["links"]["r2"]["interface"],
1233 "oil": topo["routers"]["r1"]["links"]["i1"]["interface"],
1234 },
1235 {
1236 "dut": "r1",
1237 "src_address": source,
1238 "iif": topo["routers"]["r1"]["links"]["r2"]["interface"],
1239 "oil": topo["routers"]["r1"]["links"]["i1"]["interface"],
1240 },
1241 {
1242 "dut": "r3",
1243 "src_address": source,
1244 "iif": topo["routers"]["r3"]["links"]["i2"]["interface"],
1245 "oil": topo["routers"]["r3"]["links"]["r2"]["interface"],
1246 },
1247 ]
1248 for data in input_dict_5:
1249 result = verify_mroutes(
1250 tgen,
1251 data["dut"],
1252 data["src_address"],
1253 MLD_JOIN_RANGE_1,
1254 data["iif"],
1255 data["oil"],
1256 mwait=20,
1257 )
1258 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1259
1260 step(
1261 "Verify 'show ipv6 pim upstream' showing correct OIL and IIF"
1262 " on all the nodes"
1263 )
1264 for data in input_dict_5:
1265 result = verify_upstream_iif(
1266 tgen, data["dut"], data["iif"], data["src_address"], MLD_JOIN_RANGE_1
1267 )
1268 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1269
1270 step("Delete the PIM and mld on FRR1")
1271 r1_i1 = topo["routers"]["r1"]["links"]["i1"]["interface"]
1272 input_dict_1 = {"r1": {"pim6": {"disable": [r1_i1]}}}
1273 result = create_pim_config(tgen, topo, input_dict_1)
1274 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1275
1276 input_dict_2 = {
1277 "r1": {
1278 "mld": {
1279 "interfaces": {
1280 r1_i1: {
1281 "mld": {
1282 "version": "1",
1283 "delete": True,
1284 "query": {"query-max-response-time": 10, "delete": True},
1285 }
1286 }
1287 }
1288 }
1289 }
1290 }
1291 result = create_mld_config(tgen, topo, input_dict_2)
1292 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1293
1294 step("Configure PIM on FRR")
1295 result = create_pim_config(tgen, topo["routers"])
1296 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1297
1298 step("Configure max query response timer 100sec on FRR1")
1299 input_dict_3 = {
1300 "r1": {
1301 "mld": {
1302 "interfaces": {
1303 r1_i1: {
1304 "mld": {
1305 "version": "1",
1306 "query": {"query-max-response-time": 100},
1307 }
1308 }
1309 }
1310 }
1311 }
1312 }
1313 result = create_mld_config(tgen, topo, input_dict_3)
1314 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1315
1316 result = verify_mld_config(tgen, input_dict_3)
1317 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1318
1319 step(
1320 "Remove and add max query response timer cli with different"
1321 "timer 5 times on FRR1 Enable mld and mld version 2 on FRR1"
1322 " on FRR1"
1323 )
1324
1325 input_dict_3 = {
1326 "r1": {
1327 "mld": {
1328 "interfaces": {
1329 r1_i1: {
1330 "mld": {
1331 "version": "1",
1332 "query": {"query-max-response-time": 110},
1333 }
1334 }
1335 }
1336 }
1337 }
1338 }
1339 result = create_mld_config(tgen, topo, input_dict_3)
1340 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1341
1342 result = verify_mld_config(tgen, input_dict_3)
1343 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1344
1345 input_dict_3 = {
1346 "r1": {
1347 "mld": {
1348 "interfaces": {
1349 r1_i1: {
1350 "mld": {
1351 "version": "1",
1352 "query": {"query-max-response-time": 120},
1353 }
1354 }
1355 }
1356 }
1357 }
1358 }
1359 result = create_mld_config(tgen, topo, input_dict_3)
1360 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1361
1362 result = verify_mld_config(tgen, input_dict_3)
1363 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1364
1365 input_dict_3 = {
1366 "r1": {
1367 "mld": {
1368 "interfaces": {
1369 r1_i1: {
1370 "mld": {
1371 "version": "1",
1372 "query": {"query-max-response-time": 140},
1373 }
1374 }
1375 }
1376 }
1377 }
1378 }
1379 result = create_mld_config(tgen, topo, input_dict_3)
1380 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1381
1382 result = verify_mld_config(tgen, input_dict_3)
1383 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1384
1385 input_dict_3 = {
1386 "r1": {
1387 "mld": {
1388 "interfaces": {
1389 r1_i1: {
1390 "mld": {
1391 "version": "1",
1392 "query": {"query-max-response-time": 150},
1393 }
1394 }
1395 }
1396 }
1397 }
1398 }
1399 result = create_mld_config(tgen, topo, input_dict_3)
1400 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1401
1402 result = verify_mld_config(tgen, input_dict_3)
1403 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1404
1405 step("Enable mld and mld version 2 on FRR1 on FRR1")
1406
1407 input_dict_4 = {"r1": {"mld": {"interfaces": {r1_i1: {"mld": {"version": "1"}}}}}}
1408 result = create_mld_config(tgen, topo, input_dict_4)
1409 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1410
1411 result = verify_mld_config(tgen, input_dict_3)
1412 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1413
1414 step("Verify that no core is observed")
1415 if tgen.routers_have_failure():
1416 assert False, "Testcase {}: Failed Error: {}".format(tc_name, result)
1417
1418 write_test_footer(tc_name)
1419
1420
1421def test_verify_impact_on_multicast_traffic_when_RP_removed_p0(request):
1422 """
1423 Verify removing the RP should not impact the multicast
1424 data traffic
1425 """
1426
1427 tgen = get_topogen()
1428 tc_name = request.node.name
1429 write_test_header(tc_name)
1430
1431 # Creating configuration from JSON
1432 reset_config_on_routers(tgen)
1433
1434 # Don"t run this test if we have any failure.
1435 if tgen.routers_have_failure():
1436 pytest.skip(tgen.errors)
1437
1438 step("send multicast traffic for group range ffaa::1-5")
1439
1440 step("Send multicast traffic from FRR3 to ffaa::1-5 receivers")
1441 intf_ip = topo["routers"]["i2"]["links"]["r3"]["ipv6"].split("/")[0]
1442 intf = topo["routers"]["i2"]["links"]["r3"]["interface"]
1443 result = socat_send_pim6_traffic(tgen, "i2", "UDP6-SEND", MLD_JOIN_RANGE_1, intf)
1444 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1445
1446 step("Configure static RP for group (ffaa::1) on r5")
1447 input_dict = {
1448 "r2": {
1449 "pim6": {
1450 "rp": [
1451 {
1452 "rp_addr": topo["routers"]["r2"]["links"]["lo"]["ipv6"].split(
1453 "/"
1454 )[0],
1455 "group_addr_range": GROUP_RANGE_1,
1456 }
1457 ]
1458 }
1459 }
1460 }
1461
1462 result = create_pim_config(tgen, topo, input_dict)
1463 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1464
1465 step("Enable mld on FRR1 interface and send MLD join")
1466 step("send mld join (ffaa::1-5) to R1")
1467 intf = topo["routers"]["i1"]["links"]["r1"]["interface"]
1468 intf_ip = topo["routers"]["i1"]["links"]["r1"]["ipv6"].split("/")[0]
1469 result = socat_send_mld_join(
1470 tgen, "i1", "UDP6-RECV", MLD_JOIN_RANGE_1, intf, intf_ip
1471 )
1472 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
1473
1474 step(
1475 "After SPT switchover traffic is flowing (FRR3-FRR2-FRR1)"
1476 " and (s,g) OIL updated correctly using 'show ipv6 mroute'"
1477 " 'show ipv6 pim upstream'"
1478 )
1479
1480 source = topo["routers"]["i2"]["links"]["r3"]["ipv6"].split("/")[0]
1481 input_dict = [
1482 {
1483 "dut": "r3",
1484 "src_address": source,
1485 "iif": topo["routers"]["r3"]["links"]["i2"]["interface"],
1486 "oil": topo["routers"]["r3"]["links"]["r2"]["interface"],
1487 },
1488 {
1489 "dut": "r1",
1490 "src_address": "*",
1491 "iif": topo["routers"]["r1"]["links"]["r2"]["interface"],
1492 "oil": topo["routers"]["r1"]["links"]["i1"]["interface"],
1493 },
1494 {
1495 "dut": "r1",
1496 "src_address": source,
1497 "iif": topo["routers"]["r1"]["links"]["r2"]["interface"],
1498 "oil": topo["routers"]["r1"]["links"]["i1"]["interface"],
1499 },
1500 ]
1501
1502 for data in input_dict:
1503 if data["dut"] == "r1":
1504 result = verify_mroutes(
1505 tgen,
1506 data["dut"],
1507 data["src_address"],
1508 MLD_JOIN_RANGE_1,
1509 data["iif"],
1510 data["oil"],
1511 )
1512 assert result is True, "Testcase {} : Failed Error: {}".format(
1513 tc_name, result
1514 )
1515
1516 for data in input_dict:
1517 if data["dut"] == "r3":
1518 result = verify_mroutes(
1519 tgen,
1520 data["dut"],
1521 data["src_address"],
1522 MLD_JOIN_RANGE_1,
1523 data["iif"],
1524 data["oil"],
1525 )
1526 assert result is True, "Testcase {} : Failed Error: {}".format(
1527 tc_name, result
1528 )
1529
1530 for data in input_dict:
1531 result = verify_upstream_iif(
1532 tgen, data["dut"], data["iif"], data["src_address"], MLD_JOIN_RANGE_1
1533 )
1534 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1535
1536 step("Shut and No shut RP interface in r5")
1537 dut = "r5"
1538 intf = "lo"
1539 shutdown_bringup_interface(tgen, dut, intf, False)
1540 shutdown_bringup_interface(tgen, dut, intf, True)
1541
1542 step(
1543 "After no shut of RP verify (*,G) entries re-populated again"
1544 " and uptime go reset verify using 'show ipv6 mroute'"
1545 " 'show ipv6 pim state'"
1546 )
1547
1548 for data in input_dict:
1549 result = verify_mroutes(
1550 tgen,
1551 data["dut"],
1552 data["src_address"],
1553 MLD_JOIN_RANGE_1,
1554 data["iif"],
1555 data["oil"],
1556 )
1557 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1558
1559 step("Remove static RP for group (ffaa::1) on r5")
1560 input_dict = {
1561 "r2": {
1562 "pim6": {
1563 "rp": [
1564 {
1565 "rp_addr": topo["routers"]["r2"]["links"]["lo"]["ipv6"].split(
1566 "/"
1567 )[0],
1568 "group_addr_range": GROUP_RANGE_1,
1569 "delete": True,
1570 }
1571 ]
1572 }
1573 }
1574 }
1575
1576 result = create_pim_config(tgen, topo, input_dict)
1577 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1578
1579 step("After remove of RP verify no impact on (s,g)")
1580
1581 input_dict = [
1582 {
1583 "dut": "r3",
1584 "src_address": source,
1585 "iif": topo["routers"]["r3"]["links"]["i2"]["interface"],
1586 "oil": topo["routers"]["r3"]["links"]["r2"]["interface"],
1587 },
1588 {
1589 "dut": "r1",
1590 "src_address": source,
1591 "iif": topo["routers"]["r1"]["links"]["r2"]["interface"],
1592 "oil": topo["routers"]["r1"]["links"]["i1"]["interface"],
1593 },
1594 ]
1595
1596 for data in input_dict:
1597 result = verify_mroutes(
1598 tgen,
1599 data["dut"],
1600 data["src_address"],
1601 MLD_JOIN_RANGE_1,
1602 data["iif"],
1603 data["oil"],
1604 )
1605 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1606
1607 step("verify multicast traffic is flowing")
1608 result = verify_sg_traffic(tgen, "r1", MLD_JOIN_RANGE_1, source, "ipv6")
1609 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1610
1611 write_test_footer(tc_name)
1612
1613
1614if __name__ == "__main__":
1615 args = ["-s"] + sys.argv[1:]
1616 sys.exit(pytest.main(args))