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