]>
Commit | Line | Data |
---|---|---|
40c28c86 | 1 | #!/usr/bin/env python |
acddc0ed | 2 | # SPDX-License-Identifier: ISC |
40c28c86 | 3 | |
4 | # | |
5 | # Copyright (c) 2020 by VMware, Inc. ("VMware") | |
6 | # Used Copyright (c) 2018 by Network Device Education Foundation, | |
7 | # Inc. ("NetDEF") in this file. | |
8 | # | |
40c28c86 | 9 | |
10 | """ | |
11 | Following tests are covered to test multicast pim sm: | |
12 | ||
13 | Test steps | |
14 | - Create topology (setup module) | |
15 | - Bring up topology | |
16 | ||
17 | Following tests are covered: | |
18 | 1. Verify mroute while rebooting DR /Non DR nodes( r1, r2 , r3 on all the nodes) | |
19 | """ | |
20 | ||
21 | import os | |
22 | import sys | |
23 | import json | |
24 | import time | |
25 | import datetime | |
26 | from time import sleep | |
27 | import pytest | |
28 | ||
29 | # Save the Current Working Directory to find configuration files. | |
30 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
31 | sys.path.append(os.path.join(CWD, "../")) | |
32 | sys.path.append(os.path.join(CWD, "../lib/")) | |
33 | ||
34 | # Required to instantiate the topology builder class. | |
35 | ||
36 | # pylint: disable=C0413 | |
37 | # Import topogen and topotest helpers | |
38 | from lib.topogen import Topogen, get_topogen | |
39 | ||
40 | from lib.common_config import ( | |
41 | start_topology, | |
42 | write_test_header, | |
43 | write_test_footer, | |
44 | step, | |
45 | reset_config_on_routers, | |
46 | apply_raw_config, | |
47 | add_interfaces_to_vlan, | |
48 | stop_router, | |
49 | start_router, | |
50 | check_router_status, | |
51 | topo_daemons, | |
52 | required_linux_kernel_version, | |
53 | ) | |
54 | from lib.pim import ( | |
55 | create_pim_config, | |
56 | create_igmp_config, | |
4fafd29f KK |
57 | verify_mroutes, |
58 | clear_mroute, | |
59 | clear_pim_interface_traffic, | |
40c28c86 | 60 | verify_pim_config, |
61 | verify_upstream_iif, | |
62 | verify_multicast_flag_state, | |
63 | McastTesterHelper, | |
64 | ) | |
65 | from lib.topolog import logger | |
66 | from lib.topojson import build_config_from_json | |
67 | ||
68 | HELLO_TIMER = 1 | |
69 | HOLD_TIMER = 3 | |
70 | ||
71 | pytestmark = [pytest.mark.pimd] | |
72 | ||
73 | TOPOLOGY = """ | |
74 | ||
75 | Descripton: Configuring static routes on r1/r2/r3/r4/r5 for RP reachablility. | |
76 | IPs are assigned automatically to routers, start IP and subnet is defined in respective JSON file | |
77 | JSON snippet: | |
78 | "link_ip_start": {"ipv4": "10.0.0.0", "v4mask": 24}, | |
79 | ||
80 | r5 ------- i2 | |
81 | 10.0.3.2/24| 10.0.0.2/24 | |
82 | | | |
83 | 10.0.3.1/24| | |
84 | ------------ r4 ---------- | |
85 | | 10.0.1.2/24 10.0.2.2/24 | | |
86 | 10.0.1.1/24 | | 10.0.2.1/24 | |
87 | r1 ----------- s1 ---------- r2 | |
88 | 10.0.4.2/24 | 10.0.4.3/24 | |
89 | | | |
90 | |10.0.4.4/24 | |
91 | i1 -------- r3 | |
92 | 10.0.4.1/24 | |
93 | Description: | |
94 | i1, i2 - FRR running iperf to send IGMP | |
95 | join and traffic | |
96 | r1, r2, r3, r4, r5 - FRR ruter | |
97 | s1 - OVS switch | |
98 | """ | |
99 | ||
100 | # Global variables | |
101 | VLAN_1 = 2501 | |
102 | GROUP_RANGE = "225.0.0.0/8" | |
103 | IGMP_JOIN = "225.1.1.1" | |
104 | VLAN_INTF_ADRESS_1 = "10.0.8.3/24" | |
105 | SAME_VLAN_IP_1 = {"ip": "10.1.1.1", "subnet": "255.255.255.0", "cidr": "24"} | |
106 | SAME_VLAN_IP_2 = {"ip": "10.1.1.2", "subnet": "255.255.255.0", "cidr": "24"} | |
107 | SAME_VLAN_IP_3 = {"ip": "10.1.1.3", "subnet": "255.255.255.0", "cidr": "24"} | |
108 | SAME_VLAN_IP_4 = {"ip": "10.1.1.4", "subnet": "255.255.255.0", "cidr": "24"} | |
109 | GROUP_RANGE_1 = [ | |
110 | "225.1.1.1/32", | |
111 | "225.1.1.2/32", | |
112 | "225.1.1.3/32", | |
113 | "225.1.1.4/32", | |
114 | "225.1.1.5/32", | |
115 | ] | |
116 | IGMP_JOIN_RANGE_1 = ["225.1.1.1", "225.1.1.2", "225.1.1.3", "225.1.1.4", "225.1.1.5"] | |
117 | GROUP_RANGE_2 = [ | |
118 | "226.1.1.1/32", | |
119 | "226.1.1.2/32", | |
120 | "226.1.1.3/32", | |
121 | "226.1.1.4/32", | |
122 | "226.1.1.5/32", | |
123 | ] | |
124 | IGMP_JOIN_RANGE_2 = ["226.1.1.1", "226.1.1.2", "226.1.1.3", "226.1.1.4", "226.1.1.5"] | |
125 | GROUP_RANGE_3 = [ | |
126 | "227.1.1.1/32", | |
127 | "227.1.1.2/32", | |
128 | "227.1.1.3/32", | |
129 | "227.1.1.4/32", | |
130 | "227.1.1.5/32", | |
131 | ] | |
132 | IGMP_JOIN_RANGE_3 = ["227.1.1.1", "227.1.1.2", "227.1.1.3", "227.1.1.4", "227.1.1.5"] | |
133 | ||
134 | intf_r1_s1 = None | |
135 | intf_r1_s1_addr = None | |
136 | intf_r2_s1 = None | |
137 | intf_r2_s1_addr = None | |
138 | intf_r3_s1 = None | |
139 | intf_r3_s1_addr = None | |
140 | intf_i1_s1 = None | |
141 | intf_i1_s1_addr = None | |
142 | ||
143 | ||
144 | def setup_module(mod): | |
145 | """ | |
146 | Sets up the pytest environment | |
147 | ||
148 | * `mod`: module name | |
149 | """ | |
150 | ||
151 | # Required linux kernel version for this suite to run. | |
152 | result = required_linux_kernel_version("4.19") | |
153 | if result is not True: | |
154 | pytest.skip("Kernel requirements are not met") | |
155 | ||
156 | testsuite_run_time = time.asctime(time.localtime(time.time())) | |
157 | logger.info("Testsuite start time: {}".format(testsuite_run_time)) | |
158 | logger.info("=" * 40) | |
159 | logger.info("Master Topology: \n {}".format(TOPOLOGY)) | |
160 | ||
161 | logger.info("Running setup_module to create topology") | |
162 | ||
163 | testdir = os.path.dirname(os.path.realpath(__file__)) | |
164 | json_file = "{}/pim_dr_nondr_with_static_routes_topo1.json".format(testdir) | |
165 | tgen = Topogen(json_file, mod.__name__) | |
166 | global topo | |
167 | topo = tgen.json_topo | |
168 | # ... and here it calls Mininet initialization functions. | |
169 | ||
40c28c86 | 170 | # Starting topology, create tmp files which are loaded to routers |
171 | # to start deamons and then start routers | |
991a971f | 172 | start_topology(tgen) |
40c28c86 | 173 | |
174 | # Don"t run this test if we have any failure. | |
175 | if tgen.routers_have_failure(): | |
176 | pytest.skip(tgen.errors) | |
177 | ||
178 | # Creating configuration from JSON | |
179 | build_config_from_json(tgen, tgen.json_topo) | |
180 | ||
181 | # XXX Replace this using "with McastTesterHelper()... " in each test if possible. | |
182 | global app_helper | |
183 | app_helper = McastTesterHelper(tgen) | |
184 | ||
185 | logger.info("Running setup_module() done") | |
186 | ||
187 | ||
188 | def teardown_module(): | |
189 | """Teardown the pytest environment""" | |
190 | ||
191 | logger.info("Running teardown_module to delete topology") | |
192 | ||
193 | tgen = get_topogen() | |
194 | ||
195 | app_helper.cleanup() | |
196 | ||
197 | # Stop toplogy and Remove tmp files | |
198 | tgen.stop_topology() | |
199 | ||
200 | logger.info( | |
201 | "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) | |
202 | ) | |
203 | logger.info("=" * 40) | |
204 | ||
4fafd29f | 205 | |
40c28c86 | 206 | ##################################################### |
207 | # | |
208 | # Local APIs | |
209 | # | |
210 | ##################################################### | |
211 | ||
212 | ||
213 | def pre_config_for_receiver_dr_tests( | |
214 | tgen, topo, tc_name, highest_priority, lowest_priority | |
215 | ): | |
216 | """ | |
217 | API to do common pre-configuration for receiver test cases | |
218 | ||
219 | parameters: | |
220 | ----------- | |
221 | * `tgen`: topogen object | |
222 | * `topo`: input json data | |
223 | * `tc_name`: caller test case name | |
224 | * `highest_priority`: router which will be having highest DR priority | |
225 | * `lowest_priority`: router which will be having lowest DR priority | |
226 | """ | |
227 | ||
228 | global intf_r1_s1, intf_r1_s1_addr, intf_r2_s1, intf_r2_s1_addr, intf_r3_s1, intf_r3_s1_addr, intf_i1_s1, intf_i1_s1_addr | |
229 | ||
230 | step("Configure IGMP and PIM on switch connected receiver nodes") | |
231 | step("Configure PIM on all upstream interfaces") | |
232 | ||
233 | step("Configure link between R1, R2 ,R3 and receiver on" " same vlan") | |
234 | step( | |
235 | "Make sure {0} is DR initially configuring highest IP on {0} and R2 " | |
236 | "second highest, {1} is lower".format(highest_priority, lowest_priority) | |
237 | ) | |
238 | ||
239 | intf_r1_s1 = topo["routers"]["r1"]["links"]["s1"]["interface"] | |
240 | intf_r1_s1_addr = topo["routers"]["r1"]["links"]["s1"]["ipv4"] | |
241 | ||
242 | intf_r2_s1 = topo["routers"]["r2"]["links"]["s1"]["interface"] | |
243 | intf_r2_s1_addr = topo["routers"]["r2"]["links"]["s1"]["ipv4"] | |
244 | ||
245 | intf_r3_s1 = topo["routers"]["r3"]["links"]["s1"]["interface"] | |
246 | intf_r3_s1_addr = topo["routers"]["r3"]["links"]["s1"]["ipv4"] | |
247 | ||
248 | intf_i1_s1 = topo["routers"]["i1"]["links"]["s1"]["interface"] | |
249 | intf_i1_s1_addr = topo["routers"]["i1"]["links"]["s1"]["ipv4"] | |
250 | ||
251 | if lowest_priority == "r1": | |
252 | lowest_pr_intf = intf_r1_s1 | |
253 | else: | |
254 | lowest_pr_intf = intf_r3_s1 | |
255 | ||
256 | if highest_priority == "r1": | |
257 | highest_pr_intf = intf_r1_s1 | |
258 | else: | |
259 | highest_pr_intf = intf_r3_s1 | |
260 | ||
261 | vlan_input = { | |
262 | lowest_priority: { | |
263 | "vlan": { | |
264 | VLAN_1: [ | |
265 | { | |
266 | lowest_pr_intf: { | |
267 | "ip": SAME_VLAN_IP_1["ip"], | |
268 | "subnet": SAME_VLAN_IP_1["subnet"], | |
269 | } | |
270 | } | |
271 | ] | |
272 | } | |
273 | }, | |
274 | "r2": { | |
275 | "vlan": { | |
276 | VLAN_1: [ | |
277 | { | |
278 | intf_r2_s1: { | |
279 | "ip": SAME_VLAN_IP_2["ip"], | |
280 | "subnet": SAME_VLAN_IP_2["subnet"], | |
281 | } | |
282 | } | |
283 | ] | |
284 | } | |
285 | }, | |
286 | highest_priority: { | |
287 | "vlan": { | |
288 | VLAN_1: [ | |
289 | { | |
290 | highest_pr_intf: { | |
291 | "ip": SAME_VLAN_IP_3["ip"], | |
292 | "subnet": SAME_VLAN_IP_3["subnet"], | |
293 | } | |
294 | } | |
295 | ] | |
296 | } | |
297 | }, | |
298 | "i1": { | |
299 | "vlan": { | |
300 | VLAN_1: [ | |
301 | { | |
302 | intf_i1_s1: { | |
303 | "ip": SAME_VLAN_IP_4["ip"], | |
304 | "subnet": SAME_VLAN_IP_4["subnet"], | |
305 | } | |
306 | } | |
307 | ] | |
308 | } | |
309 | }, | |
310 | } | |
311 | ||
312 | add_interfaces_to_vlan(tgen, vlan_input) | |
313 | ||
314 | raw_config = { | |
315 | "r1": { | |
316 | "raw_config": [ | |
317 | "interface {}".format(intf_r1_s1), | |
318 | "no ip address {}".format(intf_r1_s1_addr), | |
319 | "no ip pim", | |
320 | ] | |
321 | }, | |
322 | "r2": { | |
323 | "raw_config": [ | |
324 | "interface {}".format(intf_r2_s1), | |
325 | "no ip address {}".format(intf_r2_s1_addr), | |
326 | "no ip pim", | |
327 | ] | |
328 | }, | |
329 | "r3": { | |
330 | "raw_config": [ | |
331 | "interface {}".format(intf_r3_s1), | |
332 | "no ip address {}".format(intf_r3_s1_addr), | |
333 | "no ip pim", | |
334 | ] | |
335 | }, | |
336 | "i1": { | |
337 | "raw_config": [ | |
338 | "interface {}".format(intf_i1_s1), | |
339 | "no ip address {}".format(intf_i1_s1_addr), | |
340 | ] | |
341 | }, | |
342 | } | |
343 | ||
344 | result = apply_raw_config(tgen, raw_config) | |
345 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
346 | ||
347 | raw_config = { | |
348 | lowest_priority: { | |
349 | "raw_config": [ | |
350 | "interface {}.{}".format(lowest_pr_intf, VLAN_1), | |
351 | "ip address {}/{}".format(SAME_VLAN_IP_1["ip"], SAME_VLAN_IP_1["cidr"]), | |
352 | "ip pim", | |
353 | "ip igmp", | |
354 | "ip igmp version 2", | |
355 | ] | |
356 | }, | |
357 | "r2": { | |
358 | "raw_config": [ | |
359 | "interface {}.{}".format(intf_r2_s1, VLAN_1), | |
360 | "ip address {}/{}".format(SAME_VLAN_IP_2["ip"], SAME_VLAN_IP_2["cidr"]), | |
361 | "ip pim", | |
362 | "ip igmp", | |
363 | "ip igmp version 2", | |
364 | ] | |
365 | }, | |
366 | highest_priority: { | |
367 | "raw_config": [ | |
368 | "interface {}.{}".format(highest_pr_intf, VLAN_1), | |
369 | "ip address {}/{}".format(SAME_VLAN_IP_3["ip"], SAME_VLAN_IP_3["cidr"]), | |
370 | "ip pim", | |
371 | "ip igmp", | |
372 | "ip igmp version 2", | |
373 | ] | |
374 | }, | |
375 | "i1": { | |
376 | "raw_config": [ | |
377 | "interface {}.{}".format(intf_i1_s1, VLAN_1), | |
378 | "ip address {}/{}".format(SAME_VLAN_IP_4["ip"], SAME_VLAN_IP_4["cidr"]), | |
379 | ] | |
380 | }, | |
381 | } | |
382 | ||
383 | result = apply_raw_config(tgen, raw_config) | |
384 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
385 | ||
386 | for dut, intf in zip(["r1", "r2", "r3"], [intf_r1_s1, intf_r2_s1, intf_r3_s1]): | |
387 | raw_config = { | |
388 | dut: { | |
389 | "raw_config": [ | |
390 | "interface {}.{}".format(intf, VLAN_1), | |
391 | "ip pim hello {} {}".format(HELLO_TIMER, HOLD_TIMER), | |
392 | ] | |
393 | } | |
394 | } | |
395 | result = apply_raw_config(tgen, raw_config) | |
396 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
397 | ||
398 | step("Configure R4 as RP on all the nodes for group range 224.0.0.0/24") | |
399 | ||
400 | input_dict = { | |
401 | "r4": { | |
402 | "pim": { | |
403 | "rp": [ | |
404 | { | |
405 | "rp_addr": topo["routers"]["r4"]["links"]["lo"]["ipv4"].split( | |
406 | "/" | |
407 | )[0], | |
408 | "group_addr_range": GROUP_RANGE_1, | |
409 | } | |
410 | ] | |
411 | } | |
412 | } | |
413 | } | |
414 | ||
415 | result = create_pim_config(tgen, topo, input_dict) | |
416 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
417 | ||
418 | step("Send IGMP join for groups 226.1.1.1 to 226.1.1.5") | |
419 | ||
420 | vlan_intf_i1_s1 = "{}.{}".format(intf_i1_s1, VLAN_1) | |
421 | result = app_helper.run_join("i1", IGMP_JOIN_RANGE_1, join_intf=vlan_intf_i1_s1) | |
422 | assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result) | |
423 | ||
424 | step("Using static routes instead OSPF: Enable OSPF between all the nodes") | |
425 | ||
426 | step("Start traffic from R4 connected source") | |
427 | ||
428 | result = app_helper.run_traffic("i2", IGMP_JOIN_RANGE_1, "r5") | |
429 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
430 | ||
431 | return True | |
432 | ||
433 | ||
434 | def pre_config_for_source_dr_tests( | |
435 | tgen, topo, tc_name, highest_priority, lowest_priority | |
436 | ): | |
437 | """ | |
438 | API to do common pre-configuration for source test cases | |
439 | ||
440 | parameters: | |
441 | ----------- | |
442 | * `tgen`: topogen object | |
443 | * `topo`: input json data | |
444 | * `tc_name`: caller test case name | |
445 | * `highest_priority`: router which will be having highest DR priority | |
446 | * `lowest_priority`: router which will be having lowest DR priority | |
447 | """ | |
448 | ||
449 | global intf_r1_s1, intf_r1_s1_addr, intf_r2_s1, intf_r2_s1_addr, intf_r3_s1, intf_r3_s1_addr, intf_i1_s1, intf_i1_s1_addr | |
450 | ||
451 | step("Configure IGMP and PIM on switch connected receiver nodes") | |
452 | step("Configure PIM on all upstream interfaces") | |
453 | ||
454 | step("Configure link between R1, R2 ,R3 and receiver on" " same vlan") | |
455 | step( | |
456 | "Make sure {0} is DR initially configuring highest IP on {0} and R2 " | |
457 | "second highest, {1} is lower".format(highest_priority, lowest_priority) | |
458 | ) | |
459 | ||
460 | intf_r1_s1 = topo["routers"]["r1"]["links"]["s1"]["interface"] | |
461 | intf_r1_s1_addr = topo["routers"]["r1"]["links"]["s1"]["ipv4"] | |
462 | ||
463 | intf_r2_s1 = topo["routers"]["r2"]["links"]["s1"]["interface"] | |
464 | intf_r2_s1_addr = topo["routers"]["r2"]["links"]["s1"]["ipv4"] | |
465 | ||
466 | intf_r3_s1 = topo["routers"]["r3"]["links"]["s1"]["interface"] | |
467 | intf_r3_s1_addr = topo["routers"]["r3"]["links"]["s1"]["ipv4"] | |
468 | ||
469 | intf_i1_s1 = topo["routers"]["i1"]["links"]["s1"]["interface"] | |
470 | intf_i1_s1_addr = topo["routers"]["i1"]["links"]["s1"]["ipv4"] | |
471 | ||
472 | if lowest_priority == "r1": | |
473 | lowest_pr_intf = intf_r1_s1 | |
474 | else: | |
475 | lowest_pr_intf = intf_r3_s1 | |
476 | ||
477 | if highest_priority == "r1": | |
478 | highest_pr_intf = intf_r1_s1 | |
479 | else: | |
480 | highest_pr_intf = intf_r3_s1 | |
481 | ||
482 | vlan_input = { | |
483 | lowest_priority: { | |
484 | "vlan": { | |
485 | VLAN_1: [ | |
486 | { | |
487 | lowest_pr_intf: { | |
488 | "ip": SAME_VLAN_IP_1["ip"], | |
489 | "subnet": SAME_VLAN_IP_1["subnet"], | |
490 | } | |
491 | } | |
492 | ] | |
493 | } | |
494 | }, | |
495 | "r2": { | |
496 | "vlan": { | |
497 | VLAN_1: [ | |
498 | { | |
499 | intf_r2_s1: { | |
500 | "ip": SAME_VLAN_IP_2["ip"], | |
501 | "subnet": SAME_VLAN_IP_2["subnet"], | |
502 | } | |
503 | } | |
504 | ] | |
505 | } | |
506 | }, | |
507 | highest_priority: { | |
508 | "vlan": { | |
509 | VLAN_1: [ | |
510 | { | |
511 | highest_pr_intf: { | |
512 | "ip": SAME_VLAN_IP_3["ip"], | |
513 | "subnet": SAME_VLAN_IP_3["subnet"], | |
514 | } | |
515 | } | |
516 | ] | |
517 | } | |
518 | }, | |
519 | "i1": { | |
520 | "vlan": { | |
521 | VLAN_1: [ | |
522 | { | |
523 | intf_i1_s1: { | |
524 | "ip": SAME_VLAN_IP_4["ip"], | |
525 | "subnet": SAME_VLAN_IP_4["subnet"], | |
526 | } | |
527 | } | |
528 | ] | |
529 | } | |
530 | }, | |
531 | } | |
532 | ||
533 | add_interfaces_to_vlan(tgen, vlan_input) | |
534 | ||
535 | raw_config = { | |
536 | "r1": { | |
537 | "raw_config": [ | |
538 | "interface {}".format(intf_r1_s1), | |
539 | "no ip address {}".format(intf_r1_s1_addr), | |
540 | "no ip pim", | |
541 | ] | |
542 | }, | |
543 | "r2": { | |
544 | "raw_config": [ | |
545 | "interface {}".format(intf_r2_s1), | |
546 | "no ip address {}".format(intf_r2_s1_addr), | |
547 | "no ip pim", | |
548 | ] | |
549 | }, | |
550 | "r3": { | |
551 | "raw_config": [ | |
552 | "interface {}".format(intf_r3_s1), | |
553 | "no ip address {}".format(intf_r3_s1_addr), | |
554 | "no ip pim", | |
555 | ] | |
556 | }, | |
557 | "i1": { | |
558 | "raw_config": [ | |
559 | "interface {}".format(intf_i1_s1), | |
560 | "no ip address {}".format(intf_i1_s1_addr), | |
561 | ] | |
562 | }, | |
563 | } | |
564 | ||
565 | result = apply_raw_config(tgen, raw_config) | |
566 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
567 | ||
568 | step( | |
569 | "Configure IGMP and PIM on switch connected receiver nodes , " | |
570 | "configure PIM nbr with hello timer 1" | |
571 | ) | |
572 | ||
573 | raw_config = { | |
574 | lowest_priority: { | |
575 | "raw_config": [ | |
576 | "interface {}.{}".format(lowest_pr_intf, VLAN_1), | |
577 | "ip address {}/{}".format(SAME_VLAN_IP_1["ip"], SAME_VLAN_IP_1["cidr"]), | |
578 | "ip pim", | |
579 | ] | |
580 | }, | |
581 | "r2": { | |
582 | "raw_config": [ | |
583 | "interface {}.{}".format(intf_r2_s1, VLAN_1), | |
584 | "ip address {}/{}".format(SAME_VLAN_IP_2["ip"], SAME_VLAN_IP_2["cidr"]), | |
585 | "ip pim", | |
586 | ] | |
587 | }, | |
588 | highest_priority: { | |
589 | "raw_config": [ | |
590 | "interface {}.{}".format(highest_pr_intf, VLAN_1), | |
591 | "ip address {}/{}".format(SAME_VLAN_IP_3["ip"], SAME_VLAN_IP_3["cidr"]), | |
592 | "ip pim", | |
593 | ] | |
594 | }, | |
595 | "i1": { | |
596 | "raw_config": [ | |
597 | "interface {}.{}".format(intf_i1_s1, VLAN_1), | |
598 | "ip address {}/{}".format(SAME_VLAN_IP_4["ip"], SAME_VLAN_IP_4["cidr"]), | |
599 | ] | |
600 | }, | |
601 | } | |
602 | ||
603 | result = apply_raw_config(tgen, raw_config) | |
604 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
605 | ||
606 | for dut, intf in zip(["r1", "r2", "r3"], [intf_r1_s1, intf_r2_s1, intf_r3_s1]): | |
607 | raw_config = { | |
608 | dut: { | |
609 | "raw_config": [ | |
610 | "interface {}.{}".format(intf, VLAN_1), | |
611 | "ip pim hello {} {}".format(HELLO_TIMER, HOLD_TIMER), | |
612 | ] | |
613 | } | |
614 | } | |
615 | result = apply_raw_config(tgen, raw_config) | |
616 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
617 | ||
618 | step("Configure R4 as RP on all the nodes for group range 224.0.0.0/24") | |
619 | ||
620 | input_dict = { | |
621 | "r4": { | |
622 | "pim": { | |
623 | "rp": [ | |
624 | { | |
625 | "rp_addr": topo["routers"]["r4"]["links"]["lo"]["ipv4"].split( | |
626 | "/" | |
627 | )[0], | |
628 | "group_addr_range": GROUP_RANGE_1, | |
629 | } | |
630 | ] | |
631 | } | |
632 | } | |
633 | } | |
634 | ||
635 | result = create_pim_config(tgen, topo, input_dict) | |
636 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
637 | ||
638 | step("Configure IGMP on R5 port and send IGMP join for groups " "(226.1.1.1-5)") | |
639 | ||
640 | intf_r5_i2 = topo["routers"]["r5"]["links"]["i2"]["interface"] | |
641 | input_dict = { | |
642 | "r5": {"igmp": {"interfaces": {intf_r5_i2: {"igmp": {"version": "2"}}}}} | |
643 | } | |
644 | result = create_igmp_config(tgen, topo, input_dict) | |
645 | assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result) | |
646 | ||
647 | input_src = {"i2": topo["routers"]["i2"]["links"]["r5"]["interface"]} | |
648 | ||
649 | result = app_helper.run_join("i2", IGMP_JOIN_RANGE_1, "r5") | |
650 | assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result) | |
651 | ||
652 | step("Using static routes instead OSPF: Enable OSPF between all the nodes") | |
653 | ||
654 | step("Start traffic from Source node") | |
655 | ||
656 | vlan_intf_i1_s1 = "{}.{}".format(intf_i1_s1, VLAN_1) | |
657 | result = app_helper.run_traffic("i1", IGMP_JOIN_RANGE_1, bind_intf=vlan_intf_i1_s1) | |
658 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
659 | ||
660 | return True | |
661 | ||
662 | ||
663 | ##################################################### | |
664 | # | |
665 | # Testcases | |
666 | # | |
667 | ##################################################### | |
668 | ||
669 | ||
670 | def test_pim_source_dr_functionality_while_rebooting_dr_non_dr_nodes_p1(request): | |
671 | """ | |
672 | Verify mroute while rebooting DR /Non DR nodes( r1, r2 , r3 on all the nodes) | |
673 | """ | |
674 | ||
675 | tgen = get_topogen() | |
676 | tc_name = request.node.name | |
677 | write_test_header(tc_name) | |
678 | ||
679 | # Creating configuration from JSON | |
680 | app_helper.stop_all_hosts() | |
4fafd29f | 681 | clear_mroute(tgen) |
40c28c86 | 682 | check_router_status(tgen) |
683 | reset_config_on_routers(tgen) | |
4fafd29f | 684 | clear_pim_interface_traffic(tgen, topo) |
40c28c86 | 685 | |
686 | # Don"t run this test if we have any failure. | |
687 | if tgen.routers_have_failure(): | |
688 | pytest.skip(tgen.errors) | |
689 | ||
690 | result = pre_config_for_source_dr_tests(tgen, topo, tc_name, "r1", "r3") | |
691 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
692 | ||
693 | step("R1 is the DR , verify using 'show ip pim interface json'") | |
694 | ||
695 | vlan_intf_r1_s1 = "{}.{}".format(intf_r1_s1, VLAN_1) | |
696 | input_dict_dr = { | |
697 | "r1": { | |
698 | "pim": { | |
699 | "interfaces": {vlan_intf_r1_s1: {"drAddress": SAME_VLAN_IP_3["ip"]}} | |
700 | } | |
701 | } | |
702 | } | |
703 | result = verify_pim_config(tgen, input_dict_dr) | |
704 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
705 | ||
706 | step( | |
b2e37a56 | 707 | "R2 is transit router for I1 to reach R4, mroute should have (s, g) mroute with " |
40c28c86 | 708 | "OIL towards R4, using 'show ip mroute json'" |
709 | ) | |
710 | step( | |
711 | "R2 (s, g) upstream should be in join state verify using " | |
712 | "'show ip pim upstream json'" | |
713 | ) | |
714 | step( | |
715 | "R1 has (S, G) mroute with NONE OIL and upstream as not joined, verify using " | |
716 | "'show ip mroute json' 'show ip pim upstream json'" | |
717 | ) | |
718 | ||
719 | source_i1 = SAME_VLAN_IP_4["ip"] | |
720 | input_dict_r1_r2 = [ | |
721 | { | |
722 | "dut": "r1", | |
723 | "src_address": source_i1, | |
724 | "oil": "none", | |
725 | "iif": "{}.{}".format( | |
726 | topo["routers"]["r1"]["links"]["s1"]["interface"], VLAN_1 | |
727 | ), | |
728 | }, | |
729 | { | |
730 | "dut": "r2", | |
731 | "src_address": source_i1, | |
732 | "oil": topo["routers"]["r2"]["links"]["r4"]["interface"], | |
733 | "iif": "{}.{}".format( | |
734 | topo["routers"]["r2"]["links"]["s1"]["interface"], VLAN_1 | |
735 | ), | |
736 | }, | |
737 | ] | |
738 | ||
739 | for data in input_dict_r1_r2: | |
4fafd29f | 740 | result = verify_mroutes( |
40c28c86 | 741 | tgen, |
742 | data["dut"], | |
743 | data["src_address"], | |
744 | IGMP_JOIN_RANGE_1, | |
745 | data["iif"], | |
746 | data["oil"], | |
747 | ) | |
748 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
749 | ||
750 | if data["dut"] == "r2": | |
751 | result = verify_upstream_iif( | |
752 | tgen, data["dut"], data["iif"], data["src_address"], IGMP_JOIN_RANGE_1 | |
753 | ) | |
754 | assert result is True, "Testcase {} : Failed Error: {}".format( | |
755 | tc_name, result | |
756 | ) | |
757 | else: | |
758 | result = verify_upstream_iif( | |
759 | tgen, | |
760 | data["dut"], | |
761 | data["iif"], | |
762 | data["src_address"], | |
763 | IGMP_JOIN_RANGE_1, | |
764 | expected=False, | |
765 | ) | |
766 | assert result is not True, ( | |
767 | "Testcase {} : Failed \n " | |
768 | "Upstream is still joined state \n Error: {}".format(tc_name, result) | |
769 | ) | |
770 | ||
771 | step("Reboot R3 node") | |
772 | stop_router(tgen, "r3") | |
773 | ||
b2e37a56 DS |
774 | step( |
775 | "After reboot of R3 verify R1 continues to be DR, using 'show ip pim interface json'" | |
776 | ) | |
40c28c86 | 777 | |
778 | result = verify_pim_config(tgen, input_dict_dr) | |
779 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
780 | ||
781 | step("R3 should not have any mroute and upstream") | |
782 | step("R2 has mroute with OIL towards R4 /R1 , verify using 'show ip mroute'") | |
783 | step( | |
784 | "R2 has upstream with Join RejP state verify using 'show ip pim upstream json'" | |
785 | ) | |
786 | step("R1 has mroute with none OIL and upstream with Not Join") | |
787 | ||
788 | for data in input_dict_r1_r2: | |
4fafd29f | 789 | result = verify_mroutes( |
40c28c86 | 790 | tgen, |
791 | data["dut"], | |
792 | data["src_address"], | |
793 | IGMP_JOIN_RANGE_1, | |
794 | data["iif"], | |
795 | data["oil"], | |
796 | ) | |
797 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
798 | ||
799 | if data["dut"] == "r2": | |
800 | result = verify_upstream_iif( | |
801 | tgen, data["dut"], data["iif"], data["src_address"], IGMP_JOIN_RANGE_1 | |
802 | ) | |
803 | assert result is True, "Testcase {} : Failed Error: {}".format( | |
804 | tc_name, result | |
805 | ) | |
806 | else: | |
807 | result = verify_upstream_iif( | |
808 | tgen, | |
809 | data["dut"], | |
810 | data["iif"], | |
811 | data["src_address"], | |
812 | IGMP_JOIN_RANGE_1, | |
813 | expected=False, | |
814 | ) | |
815 | assert result is not True, ( | |
816 | "Testcase {} : Failed \n " | |
817 | "Upstream is still joined state \n Error: {}".format(tc_name, result) | |
818 | ) | |
819 | ||
820 | step("Reboot R2 node") | |
821 | stop_router(tgen, "r2") | |
822 | ||
b2e37a56 DS |
823 | step( |
824 | "After reboot of R2, R1 continues to be DR verify using 'show ip pim interface json'" | |
825 | ) | |
40c28c86 | 826 | |
827 | result = verify_pim_config(tgen, input_dict_dr) | |
828 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
829 | ||
830 | step( | |
831 | "R3 and R2 should not have any mroute and upstream , verify using " | |
832 | "'show ip mroute json' 'show ip pim upstream json'" | |
833 | ) | |
b2e37a56 | 834 | step("R1 has mroute created with empty OIL, using 'show ip mroute json'") |
40c28c86 | 835 | step( |
b2e37a56 | 836 | "R1 has upstream with Not Join, Rej Prune , verify using 'show ip pim upstream json'" |
40c28c86 | 837 | ) |
838 | ||
839 | for data in input_dict_r1_r2: | |
840 | if data["dut"] == "r1": | |
4fafd29f | 841 | result = verify_mroutes( |
40c28c86 | 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( | |
850 | tc_name, result | |
851 | ) | |
852 | ||
853 | result = verify_upstream_iif( | |
854 | tgen, | |
855 | data["dut"], | |
856 | data["iif"], | |
857 | data["src_address"], | |
858 | IGMP_JOIN_RANGE_1, | |
859 | expected=False, | |
860 | ) | |
861 | assert result is not True, ( | |
862 | "Testcase {} : Failed \n " | |
863 | "Upstream is still joined state \n Error: {}".format(tc_name, result) | |
864 | ) | |
865 | ||
866 | step("Reboot R1 node using FRR stop") | |
867 | stop_router(tgen, "r1") | |
868 | ||
869 | step( | |
870 | "After stop of all the routers, verify upstream and mroutes should " | |
871 | "not present in any of them" | |
872 | ) | |
873 | ||
874 | for data in input_dict_r1_r2: | |
4fafd29f | 875 | result = verify_mroutes( |
40c28c86 | 876 | tgen, |
877 | data["dut"], | |
878 | data["src_address"], | |
879 | IGMP_JOIN_RANGE_1, | |
880 | data["iif"], | |
881 | data["oil"], | |
882 | expected=False, | |
883 | ) | |
4fafd29f KK |
884 | assert ( |
885 | result is not True | |
886 | ), "Testcase {} : Failed \n " "mroutes are still present \n Error: {}".format( | |
887 | tc_name, result | |
40c28c86 | 888 | ) |
889 | ||
890 | step("start FRR for all the nodes") | |
891 | start_router(tgen, "r1") | |
892 | start_router(tgen, "r2") | |
893 | start_router(tgen, "r3") | |
894 | ||
895 | step("After start of all the routers, R1 became DR") | |
896 | ||
897 | result = verify_pim_config(tgen, input_dict_dr) | |
898 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
899 | ||
900 | for data in input_dict_r1_r2: | |
4fafd29f | 901 | result = verify_mroutes( |
40c28c86 | 902 | tgen, |
903 | data["dut"], | |
904 | data["src_address"], | |
905 | IGMP_JOIN_RANGE_1, | |
906 | data["iif"], | |
907 | data["oil"], | |
908 | ) | |
909 | assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) | |
910 | ||
911 | if data["dut"] == "r2": | |
912 | result = verify_upstream_iif( | |
913 | tgen, data["dut"], data["iif"], data["src_address"], IGMP_JOIN_RANGE_1 | |
914 | ) | |
915 | assert result is True, "Testcase {} : Failed Error: {}".format( | |
916 | tc_name, result | |
917 | ) | |
918 | ||
919 | write_test_footer(tc_name) | |
920 | ||
921 | ||
922 | if __name__ == "__main__": | |
923 | args = ["-s"] + sys.argv[1:] | |
924 | sys.exit(pytest.main(args)) |