]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/multicast-pim-sm-topo3/test_multicast_pim_sm_topo4.py
tests: Add new scenarios to test multicast-pim-sm(different topology)
[mirror_frr.git] / tests / topotests / multicast-pim-sm-topo3 / test_multicast_pim_sm_topo4.py
CommitLineData
693a44e1 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"""
24Following tests are covered to test multicast pim sm:
25
26Test steps
27- Create topology (setup module)
28- Bring up topology
29
30Following tests are covered:
31
321. TC:48 Verify mroute after configuring black-hole route for RP and source
332. TC:49 Verify mroute when RP is reachable using default route
343. TC:50 Verify mroute when LHR,FHR,RP and transit routers reachable
35 using default routes
364. TC:52 Verify PIM nbr after changing interface ip
375. TC:53 Verify IGMP interface updated with correct detail after changing interface config
386. TC:54 Verify received and transmit hello stats are getting cleared after PIM nbr reset
39
40
41"""
42
43import os
44import re
45import sys
46import json
47import time
48import datetime
49from time import sleep
50import pytest
51
52# Save the Current Working Directory to find configuration files.
53CWD = os.path.dirname(os.path.realpath(__file__))
54sys.path.append(os.path.join(CWD, "../"))
55sys.path.append(os.path.join(CWD, "../lib/"))
56
57# Required to instantiate the topology builder class.
58
59# pylint: disable=C0413
60# Import topogen and topotest helpers
61from lib.topogen import Topogen, get_topogen
62from mininet.topo import Topo
63
64from lib.common_config import (
65 start_topology,
66 write_test_header,
67 write_test_footer,
68 step,
69 iperfSendIGMPJoin,
70 addKernelRoute,
71 reset_config_on_routers,
72 iperfSendTraffic,
73 kill_iperf,
74 shutdown_bringup_interface,
75 start_router,
76 stop_router,
77 apply_raw_config,
78 create_static_routes,
79 required_linux_kernel_version,
80 topo_daemons,
81)
82from lib.pim import (
83 create_pim_config,
84 create_igmp_config,
85 verify_igmp_groups,
86 verify_ip_mroutes,
87 clear_ip_pim_interface_traffic,
88 verify_igmp_config,
89 verify_pim_neighbors,
90 verify_pim_config,
91 verify_pim_interface,
92 verify_upstream_iif,
93 clear_ip_mroute,
94 verify_multicast_traffic,
95 verify_pim_rp_info,
96 verify_pim_interface_traffic,
97 verify_igmp_interface,
98)
99from lib.topolog import logger
100from lib.topojson import build_topo_from_json, build_config_from_json
101
102# Reading the data from JSON File for topology creation
103jsonFile = "{}/multicast_pim_sm_topo4.json".format(CWD)
104try:
105 with open(jsonFile, "r") as topoJson:
106 topo = json.load(topoJson)
107except IOError:
108 assert False, "Could not read file {}".format(jsonFile)
109
110TOPOLOGY = """
111
112
113 i4-----c1-------------c2---i5
114 | |
115 | |
116 i1-----l1------r2-----f1---i2
117 | | | |
118 | | | |
119 i7 i6 i3 i8
120
121 Description:
122 i1, i2, i3. i4, i5, i6, i7, i8 - FRR running iperf to send IGMP
123 join and traffic
124 l1 - LHR
125 f1 - FHR
126 r2 - FRR router
127 c1 - FRR router
128 c2 - FRR router
129"""
130
131# Global variables
132
133GROUP_RANGE = "224.0.0.0/4"
134IGMP_GROUP = "225.1.1.1/32"
135IGMP_JOIN = "225.1.1.1"
136GROUP_RANGE_1 = [
137 "225.1.1.1/32",
138 "225.1.1.2/32",
139 "225.1.1.3/32",
140 "225.1.1.4/32",
141 "225.1.1.5/32",
142]
143IGMP_JOIN_RANGE_1 = ["225.1.1.1", "225.1.1.2", "225.1.1.3", "225.1.1.4", "225.1.1.5"]
144NEW_ADDRESS_1 = "192.168.20.1"
145NEW_ADDRESS_2 = "192.168.20.2"
146NEW_ADDRESS_1_SUBNET = "192.168.20.1/24"
147NEW_ADDRESS_2_SUBNET = "192.168.20.2/24"
148
149
150class CreateTopo(Topo):
151 """
152 Test BasicTopo - topology 1
153
154 * `Topo`: Topology object
155 """
156
157 def build(self, *_args, **_opts):
158 """Build function"""
159 tgen = get_topogen(self)
160
161 # Building topology from json file
162 build_topo_from_json(tgen, topo)
163
164
165def setup_module(mod):
166 """
167 Sets up the pytest environment
168
169 * `mod`: module name
170 """
171
172 # Required linux kernel version for this suite to run.
173 result = required_linux_kernel_version("4.19")
174 if result is not True:
175 pytest.skip("Kernel requirements are not met")
176
177 testsuite_run_time = time.asctime(time.localtime(time.time()))
178 logger.info("Testsuite start time: {}".format(testsuite_run_time))
179 logger.info("=" * 40)
180 logger.info("Master Topology: \n {}".format(TOPOLOGY))
181
182 logger.info("Running setup_module to create topology")
183
184 tgen = Topogen(CreateTopo, mod.__name__)
185 # ... and here it calls Mininet initialization functions.
186
187 # get list of daemons needs to be started for this suite.
188 daemons = topo_daemons(tgen, topo)
189
190 # Starting topology, create tmp files which are loaded to routers
191 # to start deamons and then start routers
192 start_topology(tgen, daemons)
193
194 # Don"t run this test if we have any failure.
195 if tgen.routers_have_failure():
196 pytest.skip(tgen.errors)
197
198 # Creating configuration from JSON
199 build_config_from_json(tgen, topo)
200
201 logger.info("Running setup_module() done")
202
203
204def teardown_module():
205 """Teardown the pytest environment"""
206
207 logger.info("Running teardown_module to delete topology")
208
209 tgen = get_topogen()
210
211 # Stop toplogy and Remove tmp files
212 tgen.stop_topology()
213
214 logger.info(
215 "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
216 )
217 logger.info("=" * 40)
218
219
220#####################################################
221#
222# Testcases
223#
224#####################################################
225
226
227def config_to_send_igmp_join_and_traffic(
228 tgen, topo, tc_name, iperf, iperf_intf, GROUP_RANGE, join=False, traffic=False
229):
230 """
231 API to do pre-configuration to send IGMP join and multicast
232 traffic
233
234 parameters:
235 -----------
236 * `tgen`: topogen object
237 * `topo`: input json data
238 * `tc_name`: caller test case name
239 * `iperf`: router running iperf
240 * `iperf_intf`: interface name router running iperf
241 * `GROUP_RANGE`: group range
242 * `join`: IGMP join, default False
243 * `traffic`: multicast traffic, default False
244 """
245
246 if join:
247 # Add route to kernal
248 result = addKernelRoute(tgen, iperf, iperf_intf, GROUP_RANGE)
249 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
250
251 if traffic:
252 # Add route to kernal
253 result = addKernelRoute(tgen, iperf, iperf_intf, GROUP_RANGE)
254 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
255
256 router_list = tgen.routers()
257 for router in router_list.keys():
258 if router == iperf:
259 continue
260
261 rnode = router_list[router]
262 rnode.run("echo 2 > /proc/sys/net/ipv4/conf/all/rp_filter")
263
264 for router in topo["routers"].keys():
265 if "static_routes" in topo["routers"][router]:
266 static_routes = topo["routers"][router]["static_routes"]
267 for static_route in static_routes:
268 network = static_route["network"]
269 next_hop = static_route["next_hop"]
270 if type(network) is not list:
271 network = [network]
272
273 return True
274
275
276def verify_state_incremented(state_before, state_after):
277 """
278 API to compare interface traffic state incrementing
279
280 Parameters
281 ----------
282 * `state_before` : State dictionary for any particular instance
283 * `state_after` : State dictionary for any particular instance
284 """
285
286 for router, state_data in state_before.items():
287 for state, value in state_data.items():
288 if state_before[router][state] >= state_after[router][state]:
289 errormsg = (
290 "[DUT: %s]: state %s value has not"
291 " incremented, Initial value: %s, "
292 "Current value: %s [FAILED!!]"
293 % (
294 router,
295 state,
296 state_before[router][state],
297 state_after[router][state],
298 )
299 )
300 return errormsg
301
302 logger.info(
303 "[DUT: %s]: State %s value is "
304 "incremented, Initial value: %s, Current value: %s"
305 " [PASSED!!]",
306 router,
307 state,
308 state_before[router][state],
309 state_after[router][state],
310 )
311
312 return True
313
314
315def test_mroute_when_RP_reachable_default_route_p2(request):
316 """
317 TC_49 Verify mroute when and source RP is reachable using default route
318 """
319
320 tgen = get_topogen()
321 tc_name = request.node.name
322 write_test_header(tc_name)
323
324 # Creating configuration from JSON
325 kill_iperf(tgen)
326 clear_ip_mroute(tgen)
327 reset_config_on_routers(tgen)
328 clear_ip_pim_interface_traffic(tgen, topo)
329
330 # Don"t run this test if we have any failure.
331 if tgen.routers_have_failure():
332 pytest.skip(tgen.errors)
333 step(
334 "Remove c1-c2 connected link to simulate topo "
335 "c1(FHR)---l1(RP)----r2---f1-----c2(LHR)"
336 )
337
338 intf_c1_c2 = topo["routers"]["c1"]["links"]["c2"]["interface"]
339 intf_c2_c1 = topo["routers"]["c2"]["links"]["c1"]["interface"]
340 shutdown_bringup_interface(tgen, "c1", intf_c1_c2, False)
341 shutdown_bringup_interface(tgen, "c2", intf_c2_c1, False)
342
343 step("Enable the PIM on all the interfaces of FRR1, FRR2, FRR3")
344 step(
345 "Enable IGMP of FRR1 interface and send IGMP joins "
346 " from FRR1 node for group range (225.1.1.1-5)"
347 )
348
349 intf_c2_i5 = topo["routers"]["c2"]["links"]["i5"]["interface"]
350 input_dict = {
351 "c2": {"igmp": {"interfaces": {intf_c2_i5: {"igmp": {"version": "2"}}}}}
352 }
353 result = create_igmp_config(tgen, topo, input_dict)
354 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
355
356 input_join = {"i5": topo["routers"]["i5"]["links"]["c2"]["interface"]}
357
358 for recvr, recvr_intf in input_join.items():
359 result = config_to_send_igmp_join_and_traffic(
360 tgen, topo, tc_name, recvr, recvr_intf, GROUP_RANGE_1, join=True
361 )
362 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
363
364 result = iperfSendIGMPJoin(tgen, recvr, IGMP_JOIN_RANGE_1, join_interval=1)
365 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
366
367 step("Configure static RP for (225.1.1.1-5) as R2")
368
369 input_dict = {
370 "l1": {
371 "pim": {
372 "rp": [
373 {
374 "rp_addr": topo["routers"]["l1"]["links"]["lo"]["ipv4"].split(
375 "/"
376 )[0],
377 "group_addr_range": GROUP_RANGE,
378 }
379 ]
380 }
381 }
382 }
383
384 result = create_pim_config(tgen, topo, input_dict)
385 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
386
387 step("Send traffic from C1 to all the groups ( 225.1.1.1 to 225.1.1.5)")
388
389 input_src = {"i4": topo["routers"]["i4"]["links"]["c1"]["interface"]}
390
391 for src, src_intf in input_src.items():
392 result = config_to_send_igmp_join_and_traffic(
393 tgen, topo, tc_name, src, src_intf, GROUP_RANGE_1, traffic=True
394 )
395 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
396
397 result = iperfSendTraffic(tgen, src, IGMP_JOIN_RANGE_1, 32, 2500)
398 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
399
400 source_i4 = topo["routers"]["i4"]["links"]["c1"]["ipv4"].split("/")[0]
401
402 input_dict_starg = [
403 {
404 "dut": "c2",
405 "src_address": "*",
406 "iif": topo["routers"]["c2"]["links"]["f1"]["interface"],
407 "oil": topo["routers"]["c2"]["links"]["i5"]["interface"],
408 }
409 ]
410
411 input_dict_sg = [
412 {
413 "dut": "c2",
414 "src_address": source_i4,
415 "iif": topo["routers"]["c2"]["links"]["f1"]["interface"],
416 "oil": topo["routers"]["c2"]["links"]["i5"]["interface"],
417 }
418 ]
419
420 step("Verify mroutes and iff upstream")
421
422 for data in input_dict_sg:
423 result = verify_ip_mroutes(
424 tgen,
425 data["dut"],
426 data["src_address"],
427 IGMP_JOIN_RANGE_1,
428 data["iif"],
429 data["oil"],
430 )
431 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
432
433 result = verify_upstream_iif(
434 tgen, data["dut"], data["iif"], data["src_address"], IGMP_JOIN_RANGE_1
435 )
436 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
437
438 for data in input_dict_starg:
439 result = verify_ip_mroutes(
440 tgen,
441 data["dut"],
442 data["src_address"],
443 IGMP_JOIN_RANGE_1,
444 data["iif"],
445 data["oil"],
446 )
447 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
448
449 result = verify_upstream_iif(
450 tgen, data["dut"], data["iif"], data["src_address"], IGMP_JOIN_RANGE_1
451 )
452 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
453
454 step("Delete static routes on c2")
455 input_dict = {
456 "c2": {
457 "static_routes": [
458 {
459 "network": ["1.0.4.11/32", "10.0.2.1/24", "10.0.1.2/24"],
460 "next_hop": "10.0.3.2",
461 "delete": True,
462 }
463 ]
464 }
465 }
466
467 result = create_static_routes(tgen, input_dict)
468 assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
469
470 step("Verify RP info unknown after removing static route from c2 ")
471 dut = "c2"
472 rp_address = topo["routers"]["l1"]["links"]["lo"]["ipv4"].split("/")[0]
473 SOURCE = "Static"
474 result = verify_pim_rp_info(
475 tgen, topo, dut, GROUP_RANGE_1, "Unknown", rp_address, SOURCE
476 )
477 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
478
479 step("Verify mroute not present after Delete of static routes on c1")
480
481 for data in input_dict_sg:
482 result = verify_ip_mroutes(
483 tgen,
484 data["dut"],
485 data["src_address"],
486 IGMP_JOIN_RANGE_1,
487 data["iif"],
488 data["oil"],
489 expected=False,
490 )
491 assert result is not True, "Testcase {} : Failed Error: {}".format(
492 tc_name, result
493 )
494
495 result = verify_upstream_iif(
496 tgen,
497 data["dut"],
498 data["iif"],
499 data["src_address"],
500 IGMP_JOIN_RANGE_1,
501 expected=False,
502 )
503 assert result is not True, "Testcase {} : Failed Error: {}".format(
504 tc_name, result
505 )
506
507 for data in input_dict_starg:
508 result = verify_ip_mroutes(
509 tgen,
510 data["dut"],
511 data["src_address"],
512 IGMP_JOIN_RANGE_1,
513 data["iif"],
514 data["oil"],
515 expected=False,
516 )
517 assert result is not True, "Testcase {} : Failed Error: {}".format(
518 tc_name, result
519 )
520
521 result = verify_upstream_iif(
522 tgen,
523 data["dut"],
524 data["iif"],
525 data["src_address"],
526 IGMP_JOIN_RANGE_1,
527 expected=False,
528 )
529 assert result is not True, "Testcase {} : Failed Error: {}".format(
530 tc_name, result
531 )
532
533 step("Configure default routes on c2")
534
535 intf_f1_c2 = topo["routers"]["f1"]["links"]["c2"]["ipv4"].split("/")[0]
536
537 input_dict = {
538 "c2": {"static_routes": [{"network": "0.0.0.0/0", "next_hop": intf_f1_c2}]}
539 }
540 result = create_static_routes(tgen, input_dict)
541 assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
542
543 step("applying ip nht config on c2")
544
545 raw_config = {"c2": {"raw_config": ["ip nht resolve-via-default"]}}
546
547 result = apply_raw_config(tgen, raw_config)
548 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
549
550 step("Verify RP info is NOT unknown after removing static route from c2 ")
551 result = verify_pim_rp_info(
552 tgen, topo, dut, GROUP_RANGE_1, "Unknown", rp_address, SOURCE, expected=False
553 )
554 assert result is not True, "Testcase {} :Failed \n Error: {}".format(
555 tc_name, result
556 )
557
558 step("Verify (s,g) populated after adding default route ")
559
560 for data in input_dict_sg:
561 result = verify_ip_mroutes(
562 tgen,
563 data["dut"],
564 data["src_address"],
565 IGMP_JOIN_RANGE_1,
566 data["iif"],
567 data["oil"],
568 )
569 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
570
571 result = verify_upstream_iif(
572 tgen, data["dut"], data["iif"], data["src_address"], IGMP_JOIN_RANGE_1
573 )
574 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
575
576 step("Verify (*,g) populated after adding default route ")
577
578 for data in input_dict_starg:
579 result = verify_ip_mroutes(
580 tgen,
581 data["dut"],
582 data["src_address"],
583 IGMP_JOIN_RANGE_1,
584 data["iif"],
585 data["oil"],
586 )
587 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
588
589 result = verify_upstream_iif(
590 tgen, data["dut"], data["iif"], data["src_address"], IGMP_JOIN_RANGE_1
591 )
592 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
593
594 write_test_footer(tc_name)
595
596
597def test_mroute_with_RP_default_route_all_nodes_p2(request):
598 """
599 TC_50 Verify mroute when LHR,FHR,RP and transit routers reachable
600 using default routes
601 """
602
603 tgen = get_topogen()
604 tc_name = request.node.name
605 write_test_header(tc_name)
606
607 # Creating configuration from JSON
608 kill_iperf(tgen)
609 clear_ip_mroute(tgen)
610 reset_config_on_routers(tgen)
611 clear_ip_pim_interface_traffic(tgen, topo)
612
613 # Don"t run this test if we have any failure.
614 if tgen.routers_have_failure():
615 pytest.skip(tgen.errors)
616 step(
617 "Remove c1-c2 connected link to simulate topo "
618 "c1(LHR)---l1(RP)----r2---f1-----c2(FHR)"
619 )
620
621 intf_c1_c2 = topo["routers"]["c1"]["links"]["c2"]["interface"]
622 intf_c2_c1 = topo["routers"]["c2"]["links"]["c1"]["interface"]
623 shutdown_bringup_interface(tgen, "c1", intf_c1_c2, False)
624 shutdown_bringup_interface(tgen, "c2", intf_c2_c1, False)
625
626 step("Enable the PIM on all the interfaces of FRR1, FRR2, FRR3")
627 step(
628 "Enable IGMP of FRR1 interface and send IGMP joins "
629 " from FRR1 node for group range (225.1.1.1-5)"
630 )
631
632 intf_c1_i4 = topo["routers"]["c1"]["links"]["i4"]["interface"]
633 input_dict = {
634 "c1": {"igmp": {"interfaces": {intf_c1_i4: {"igmp": {"version": "2"}}}}}
635 }
636 result = create_igmp_config(tgen, topo, input_dict)
637 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
638
639 input_join = {"i4": topo["routers"]["i4"]["links"]["c1"]["interface"]}
640
641 for recvr, recvr_intf in input_join.items():
642 result = config_to_send_igmp_join_and_traffic(
643 tgen, topo, tc_name, recvr, recvr_intf, GROUP_RANGE_1, join=True
644 )
645 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
646
647 result = iperfSendIGMPJoin(tgen, recvr, IGMP_JOIN_RANGE_1, join_interval=1)
648 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
649
650 step("Configure static RP for (225.1.1.1-5) as R2")
651
652 input_dict = {
653 "l1": {
654 "pim": {
655 "rp": [
656 {
657 "rp_addr": topo["routers"]["l1"]["links"]["lo"]["ipv4"].split(
658 "/"
659 )[0],
660 "group_addr_range": GROUP_RANGE,
661 }
662 ]
663 }
664 }
665 }
666
667 result = create_pim_config(tgen, topo, input_dict)
668 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
669
670 step("Send traffic from C2 to all the groups ( 225.1.1.1 to 225.1.1.5)")
671
672 input_src = {"i5": topo["routers"]["i5"]["links"]["c2"]["interface"]}
673
674 for src, src_intf in input_src.items():
675 result = config_to_send_igmp_join_and_traffic(
676 tgen, topo, tc_name, src, src_intf, GROUP_RANGE_1, traffic=True
677 )
678 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
679
680 result = iperfSendTraffic(tgen, src, IGMP_JOIN_RANGE_1, 32, 2500)
681 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
682
683 source_i5 = topo["routers"]["i5"]["links"]["c2"]["ipv4"].split("/")[0]
684
685 input_dict_starg = [
686 {
687 "dut": "c1",
688 "src_address": "*",
689 "iif": topo["routers"]["c1"]["links"]["l1"]["interface"],
690 "oil": topo["routers"]["c1"]["links"]["i4"]["interface"],
691 }
692 ]
693
694 input_dict_sg = [
695 {
696 "dut": "c1",
697 "src_address": source_i5,
698 "iif": topo["routers"]["c1"]["links"]["l1"]["interface"],
699 "oil": topo["routers"]["c1"]["links"]["i4"]["interface"],
700 }
701 ]
702
703 step("Verify mroutes and iff upstream")
704
705 for data in input_dict_sg:
706 result = verify_ip_mroutes(
707 tgen,
708 data["dut"],
709 data["src_address"],
710 IGMP_JOIN_RANGE_1,
711 data["iif"],
712 data["oil"],
713 )
714 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
715
716 result = verify_upstream_iif(
717 tgen, data["dut"], data["iif"], data["src_address"], IGMP_JOIN_RANGE_1
718 )
719 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
720
721 for data in input_dict_starg:
722 result = verify_ip_mroutes(
723 tgen,
724 data["dut"],
725 data["src_address"],
726 IGMP_JOIN_RANGE_1,
727 data["iif"],
728 data["oil"],
729 )
730 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
731
732 result = verify_upstream_iif(
733 tgen, data["dut"], data["iif"], data["src_address"], IGMP_JOIN_RANGE_1
734 )
735 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
736
737 step("Delete static routes RP on all the nodes")
738 input_dict = {
739 "c2": {
740 "static_routes": [
741 {"network": ["1.0.4.11/32"], "next_hop": "10.0.3.2", "delete": True}
742 ]
743 },
744 "c1": {
745 "static_routes": [
746 {"network": ["1.0.4.11/32"], "next_hop": "10.0.2.2", "delete": True}
747 ]
748 },
749 "r2": {
750 "static_routes": [
751 {"network": ["1.0.4.11/32"], "next_hop": "10.0.12.1", "delete": True}
752 ]
753 },
754 "f1": {
755 "static_routes": [
756 {"network": ["1.0.4.11/32"], "next_hop": "10.0.7.2", "delete": True}
757 ]
758 },
759 }
760
761 result = create_static_routes(tgen, input_dict)
762 assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
763
764 step("Verify RP info unknown after removing static route from c2 ")
765 dut = "c2"
766 rp_address = topo["routers"]["l1"]["links"]["lo"]["ipv4"].split("/")[0]
767 SOURCE = "Static"
768 result = verify_pim_rp_info(
769 tgen, topo, dut, GROUP_RANGE_1, "Unknown", rp_address, SOURCE
770 )
771 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
772
773 for data in input_dict_starg:
774 result = verify_ip_mroutes(
775 tgen,
776 data["dut"],
777 data["src_address"],
778 IGMP_JOIN_RANGE_1,
779 data["iif"],
780 data["oil"],
781 expected=False,
782 )
783 assert result is not True, "Testcase {} : Failed Error: {}".format(
784 tc_name, result
785 )
786
787 result = verify_upstream_iif(
788 tgen,
789 data["dut"],
790 data["iif"],
791 data["src_address"],
792 IGMP_JOIN_RANGE_1,
793 expected=False,
794 )
795 assert result is not True, "Testcase {} : Failed Error: {}".format(
796 tc_name, result
797 )
798
799 step("Configure default routes on all the nodes")
800
801 intf_f1_c2 = topo["routers"]["f1"]["links"]["c2"]["ipv4"].split("/")[0]
802 intf_l1_c1 = topo["routers"]["l1"]["links"]["c1"]["ipv4"].split("/")[0]
803 intf_l1_r2 = topo["routers"]["l1"]["links"]["r2"]["ipv4"].split("/")[0]
804 intf_r2_f1 = topo["routers"]["r2"]["links"]["f1"]["ipv4"].split("/")[0]
805
806 input_dict = {
807 "c1": {"static_routes": [{"network": "0.0.0.0/0", "next_hop": intf_l1_c1}]},
808 "c2": {"static_routes": [{"network": "0.0.0.0/0", "next_hop": intf_f1_c2}]},
809 "r2": {"static_routes": [{"network": "0.0.0.0/0", "next_hop": intf_l1_r2}]},
810 "f1": {"static_routes": [{"network": "0.0.0.0/0", "next_hop": intf_r2_f1}]},
811 }
812 result = create_static_routes(tgen, input_dict)
813 assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
814
815 step("applying ip nht config on c2")
816
817 raw_config = {
818 "c1": {"raw_config": ["ip nht resolve-via-default"]},
819 "c2": {"raw_config": ["ip nht resolve-via-default"]},
820 "r2": {"raw_config": ["ip nht resolve-via-default"]},
821 "f1": {"raw_config": ["ip nht resolve-via-default"]},
822 "l1": {"raw_config": ["ip nht resolve-via-default"]},
823 }
824
825 result = apply_raw_config(tgen, raw_config)
826 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
827
828 step("Verify RP info Not unknown after removing static route from c2 ")
829 dut = "c2"
830 step("Verify RP info is NOT unknown after removing static route from c2 ")
831 result = verify_pim_rp_info(
832 tgen, topo, dut, GROUP_RANGE_1, "Unknown", rp_address, SOURCE, expected=False
833 )
834 assert result is not True, "Testcase {} :Failed \n Error: {}".format(
835 tc_name, result
836 )
837
838 step("Verify (s,g) populated after adding default route ")
839
840 for data in input_dict_sg:
841 result = verify_ip_mroutes(
842 tgen,
843 data["dut"],
844 data["src_address"],
845 IGMP_JOIN_RANGE_1,
846 data["iif"],
847 data["oil"],
848 )
849 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
850
851 result = verify_upstream_iif(
852 tgen, data["dut"], data["iif"], data["src_address"], IGMP_JOIN_RANGE_1
853 )
854 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
855
856 step("Verify (*,g) populated after adding default route ")
857
858 for data in input_dict_starg:
859 result = verify_ip_mroutes(
860 tgen,
861 data["dut"],
862 data["src_address"],
863 IGMP_JOIN_RANGE_1,
864 data["iif"],
865 data["oil"],
866 )
867 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
868
869 result = verify_upstream_iif(
870 tgen, data["dut"], data["iif"], data["src_address"], IGMP_JOIN_RANGE_1
871 )
872 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
873
874 write_test_footer(tc_name)
875
876
877def test_PIM_hello_tx_rx_p1(request):
878 """
879 TC_54 Verify received and transmit hello stats
880 are getting cleared after PIM nbr reset
881 """
882
883 tgen = get_topogen()
884 tc_name = request.node.name
885 write_test_header(tc_name)
886
887 # Creating configuration from JSON
888 kill_iperf(tgen)
889 clear_ip_mroute(tgen)
890 reset_config_on_routers(tgen)
891 clear_ip_pim_interface_traffic(tgen, topo)
892
893 # Don"t run this test if we have any failure.
894 if tgen.routers_have_failure():
895 pytest.skip(tgen.errors)
896 step(
897 "Remove c1-c2 connected link to simulate topo "
898 "c1(LHR)---l1(RP)----r2---f1-----c2(FHR)"
899 )
900
901 intf_c1_c2 = topo["routers"]["c1"]["links"]["c2"]["interface"]
902 intf_c2_c1 = topo["routers"]["c2"]["links"]["c1"]["interface"]
903 shutdown_bringup_interface(tgen, "c1", intf_c1_c2, False)
904 shutdown_bringup_interface(tgen, "c2", intf_c2_c1, False)
905
906 step("Enable the PIM on all the interfaces of FRR1, FRR2, FRR3")
907 step(
908 "Enable IGMP of FRR1 interface and send IGMP joins "
909 " from FRR1 node for group range (225.1.1.1-5)"
910 )
911
912 intf_c1_i4 = topo["routers"]["c1"]["links"]["i4"]["interface"]
913 input_dict = {
914 "c1": {"igmp": {"interfaces": {intf_c1_i4: {"igmp": {"version": "2"}}}}}
915 }
916 result = create_igmp_config(tgen, topo, input_dict)
917 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
918
919 input_join = {"i4": topo["routers"]["i4"]["links"]["c1"]["interface"]}
920
921 for recvr, recvr_intf in input_join.items():
922 result = config_to_send_igmp_join_and_traffic(
923 tgen, topo, tc_name, recvr, recvr_intf, GROUP_RANGE_1, join=True
924 )
925 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
926
927 result = iperfSendIGMPJoin(tgen, recvr, IGMP_JOIN_RANGE_1, join_interval=1)
928 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
929
930 step("Configure static RP for (225.1.1.1-5) as R2")
931
932 input_dict = {
933 "l1": {
934 "pim": {
935 "rp": [
936 {
937 "rp_addr": topo["routers"]["l1"]["links"]["lo"]["ipv4"].split(
938 "/"
939 )[0],
940 "group_addr_range": GROUP_RANGE,
941 }
942 ]
943 }
944 }
945 }
946
947 result = create_pim_config(tgen, topo, input_dict)
948 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
949
950 step("Send Mcast traffic from C2 to all the groups ( 225.1.1.1 to 225.1.1.5)")
951
952 input_src = {"i5": topo["routers"]["i5"]["links"]["c2"]["interface"]}
953
954 for src, src_intf in input_src.items():
955 result = config_to_send_igmp_join_and_traffic(
956 tgen, topo, tc_name, src, src_intf, GROUP_RANGE_1, traffic=True
957 )
958 assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
959
960 result = iperfSendTraffic(tgen, src, IGMP_JOIN_RANGE_1, 32, 2500)
961 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
962
963 source_i5 = topo["routers"]["i5"]["links"]["c2"]["ipv4"].split("/")[0]
964
965 input_dict_starg = [
966 {
967 "dut": "c1",
968 "src_address": "*",
969 "iif": topo["routers"]["c1"]["links"]["l1"]["interface"],
970 "oil": topo["routers"]["c1"]["links"]["i4"]["interface"],
971 }
972 ]
973
974 input_dict_sg = [
975 {
976 "dut": "c1",
977 "src_address": source_i5,
978 "iif": topo["routers"]["c1"]["links"]["l1"]["interface"],
979 "oil": topo["routers"]["c1"]["links"]["i4"]["interface"],
980 }
981 ]
982
983 step("(*,G) and (S,G) created on f1 and node verify using 'show ip mroute'")
984 for data in input_dict_sg:
985 result = verify_ip_mroutes(
986 tgen,
987 data["dut"],
988 data["src_address"],
989 IGMP_JOIN_RANGE_1,
990 data["iif"],
991 data["oil"],
992 )
993 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
994
995 for data in input_dict_starg:
996 result = verify_ip_mroutes(
997 tgen,
998 data["dut"],
999 data["src_address"],
1000 IGMP_JOIN_RANGE_1,
1001 data["iif"],
1002 data["oil"],
1003 )
1004 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1005
1006 intf_l1_c1 = topo["routers"]["l1"]["links"]["c1"]["interface"]
1007 intf_c1_l1 = topo["routers"]["c1"]["links"]["l1"]["interface"]
1008
1009 step("verify before stats on C1")
1010 state_dict = {"c1": {intf_c1_l1: ["helloTx", "helloRx"],}}
1011
1012 c1_state_before = verify_pim_interface_traffic(tgen, state_dict)
1013 assert isinstance(
1014 c1_state_before, dict
1015 ), "Testcase{} : Failed \n state_before is not dictionary \n "
1016 "Error: {}".format(tc_name, result)
1017
1018 step("Flap PIM nbr while doing interface c1-l1 interface shut from f1 side")
1019 shutdown_bringup_interface(tgen, "c1", intf_c1_l1, False)
1020
1021 step(
1022 "After shut of local interface from c1 , verify rx/tx hello counters are cleared on c1 side"
1023 "verify using 'show ip pim interface traffic'"
1024 )
1025 shutdown_bringup_interface(tgen, "c1", intf_c1_l1, True)
1026
1027 step("verify stats after on c1")
1028 c1_state_after = verify_pim_interface_traffic(tgen, state_dict)
1029 assert isinstance(
1030 c1_state_after, dict
1031 ), "Testcase{} : Failed \n state_before is not dictionary \n "
1032 "Error: {}".format(tc_name, result)
1033
1034 step("verify stats not increamented on c1")
1035 result = verify_state_incremented(c1_state_before, c1_state_after)
1036 assert (
1037 result is not True
1038 ), "Testcase{} : Failed Error: {}" "stats incremented".format(tc_name, result)
1039
1040 step("verify before stats on l1")
1041 l1_state_dict = {"l1": {intf_l1_c1: ["helloTx", "helloRx"],}}
1042
1043 l1_state_before = verify_pim_interface_traffic(tgen, l1_state_dict)
1044 assert isinstance(
1045 l1_state_before, dict
1046 ), "Testcase{} : Failed \n state_before is not dictionary \n "
1047 "Error: {}".format(tc_name, result)
1048
1049 step("Flap PIM nbr while doing interface r2-c1 shut from r2 side")
1050 shutdown_bringup_interface(tgen, "l1", intf_l1_c1, False)
1051
1052 step(
1053 "After shut the interface from r2 side , verify r2 side rx and tx of hello"
1054 "counters are resetted show ip pim interface traffic"
1055 )
1056 shutdown_bringup_interface(tgen, "l1", intf_l1_c1, True)
1057
1058 step("verify stats after on l1")
1059 l1_state_after = verify_pim_interface_traffic(tgen, l1_state_dict)
1060 assert isinstance(
1061 l1_state_after, dict
1062 ), "Testcase{} : Failed \n state_before is not dictionary \n "
1063 "Error: {}".format(tc_name, result)
1064
1065 step("verify stats not increamented on l1")
1066 result = verify_state_incremented(l1_state_before, l1_state_after)
1067 assert (
1068 result is not True
1069 ), "Testcase{} : Failed Error: {}" "stats incremented".format(tc_name, result)
1070
1071 step("Reinit the dict")
1072 c1_state_before = {}
1073 l1_state_before = {}
1074 c1_state_after = {}
1075 l1_state_after = {}
1076
1077 step("verify before stats on C1")
1078 state_dict = {"c1": {intf_c1_l1: ["helloTx", "helloRx"],}}
1079
1080 c1_state_before = verify_pim_interface_traffic(tgen, state_dict)
1081 assert isinstance(
1082 c1_state_before, dict
1083 ), "Testcase{} : Failed \n state_before is not dictionary \n "
1084 "Error: {}".format(tc_name, result)
1085
1086 step("Flap c1-r2 pim nbr while changing ip address from c1 side")
1087 c1_l1_ip_subnet = topo["routers"]["c1"]["links"]["l1"]["ipv4"]
1088
1089 raw_config = {
1090 "c1": {
1091 "raw_config": [
1092 "interface {}".format(intf_c1_l1),
1093 "no ip address {}".format(c1_l1_ip_subnet),
1094 "ip address {}".format(NEW_ADDRESS_2_SUBNET),
1095 ]
1096 }
1097 }
1098
1099 result = apply_raw_config(tgen, raw_config)
1100 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
1101
1102 step("verify stats after on c1")
1103 c1_state_after = verify_pim_interface_traffic(tgen, state_dict)
1104 assert isinstance(
1105 c1_state_after, dict
1106 ), "Testcase{} : Failed \n state_before is not dictionary \n "
1107 "Error: {}".format(tc_name, result)
1108
1109 step("verify stats not increamented on c1")
1110 result = verify_state_incremented(c1_state_before, c1_state_after)
1111 assert (
1112 result is not True
1113 ), "Testcase{} : Failed Error: {}" "stats incremented".format(tc_name, result)
1114
1115 write_test_footer(tc_name)
1116
1117
1118if __name__ == "__main__":
1119 args = ["-s"] + sys.argv[1:]
1120 sys.exit(pytest.main(args))