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