]>
git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/pim_acl/test_pim_acl.py
2 # SPDX-License-Identifier: ISC
6 # Part of NetDEF Topology Tests
8 # Copyright (c) 2020 by
9 # Network Device Education Foundation, Inc. ("NetDEF")
13 test_pim_acl.py: Test PIM with RP selection using ACLs
16 # Test PIM RP selection with ACLs
18 # Testing RP selection with ACLs. R1 uses multiple ACLs
19 # to select desired RPs (R11 to R15)
23 # Create topology. Hosts are only using zebra/staticd,
24 # no PIM, no OSPF (using IGMPv2 for multicast)
25 # - test_ospf_convergence()
26 # Wait for OSPF convergence in each VRF. OSPF is run on
28 # - test_pim_convergence()
29 # Wait for PIM convergence on all routers. PIM is run on
31 # - test_mcast_acl_1():
32 # Test 1st ACL entry 239.100.0.0/28 with 239.100.0.1 which
33 # should use R11 as RP
34 # Stop multicast after verification
35 # - test_mcast_acl_2():
36 # Test 2nd ACL entry 239.100.0.17/32 with 239.100.0.17 which
37 # should use R12 as RP
38 # Stop multicast after verification
39 # - test_mcast_acl_3():
40 # Test 3rd ACL entry 239.100.0.32/27 with 239.100.0.32 which
41 # should use R13 as RP
42 # Stop multicast after verification
43 # - test_mcast_acl_4():
44 # Test 4th ACL entry 239.100.0.128/25 with 239.100.0.255 which
45 # should use R14 as RP
46 # Stop multicast after verification
47 # - test_mcast_acl_5():
48 # Test 5th ACL entry 239.100.0.96/28 with 239.100.0.97 which
49 # should use R14 as RP
50 # Stop multicast after verification
51 # - test_mcast_acl_6():
52 # Test 6th ACL entry 239.100.0.64/28 with 239.100.0.70 which
53 # should use R15 as RP
54 # Stop multicast after verification
59 # XXX clean up in later commit to avoid conflict on rebase
60 # pylint: disable=C0413
67 +-----------+ | +----------+
68 | | .1 | .11 | Host R11 |
69 +---------+ | R1 |---------+--------| PIM RP |
70 | Host H1 | 192.168.100.0/24 | | 192.168.101.0/24 +----------+
71 | receive |------------------| uses ACLs | | +----------+
72 |IGMP JOIN| .10 .1 | to pick | | .12 | Host R12 |
73 +---------+ | RP | +--------| PIM RP |
75 +-----------+ | +----------+
95 # Save the Current Working Directory to find configuration files.
96 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
97 sys
.path
.append(os
.path
.join(CWD
, "../"))
99 # pylint: disable=C0413
100 # Import topogen and topotest helpers
101 from lib
import topotest
102 from lib
.topogen
import Topogen
, TopoRouter
, get_topogen
103 from lib
.topolog
import logger
105 # Required to instantiate the topology builder class.
106 from lib
.pim
import McastTesterHelper
108 pytestmark
= [pytest
.mark
.pimd
, pytest
.mark
.ospfd
]
111 def build_topo(tgen
):
112 for hostNum
in range(1, 3):
113 tgen
.add_router("h{}".format(hostNum
))
115 # Create the main router
116 tgen
.add_router("r1")
118 # Create the PIM RP routers
119 for rtrNum
in range(11, 16):
120 tgen
.add_router("r{}".format(rtrNum
))
122 # Setup Switches and connections
123 for swNum
in range(1, 3):
124 tgen
.add_switch("sw{}".format(swNum
))
126 # Add connections H1 to R1 switch sw1
127 tgen
.gears
["h1"].add_link(tgen
.gears
["sw1"])
128 tgen
.gears
["r1"].add_link(tgen
.gears
["sw1"])
130 # Add connections R1 to R1x switch sw2
131 tgen
.gears
["r1"].add_link(tgen
.gears
["sw2"])
132 tgen
.gears
["h2"].add_link(tgen
.gears
["sw2"])
133 tgen
.gears
["r11"].add_link(tgen
.gears
["sw2"])
134 tgen
.gears
["r12"].add_link(tgen
.gears
["sw2"])
135 tgen
.gears
["r13"].add_link(tgen
.gears
["sw2"])
136 tgen
.gears
["r14"].add_link(tgen
.gears
["sw2"])
137 tgen
.gears
["r15"].add_link(tgen
.gears
["sw2"])
140 #####################################################
144 #####################################################
147 def setup_module(module
):
148 logger
.info("PIM RP ACL Topology: \n {}".format(TOPOLOGY
))
150 tgen
= Topogen(build_topo
, module
.__name
__)
151 tgen
.start_topology()
154 router_list
= tgen
.routers()
156 for rname
, router
in router_list
.items():
157 logger
.info("Loading router %s" % rname
)
159 TopoRouter
.RD_ZEBRA
, os
.path
.join(CWD
, "{}/zebra.conf".format(rname
))
162 # Only load ospf on routers, not on end hosts
164 TopoRouter
.RD_OSPF
, os
.path
.join(CWD
, "{}/ospfd.conf".format(rname
))
167 TopoRouter
.RD_PIM
, os
.path
.join(CWD
, "{}/pimd.conf".format(rname
))
172 def teardown_module(module
):
177 def test_ospf_convergence():
178 "Test for OSPFv2 convergence"
181 # Skip if previous fatal error condition is raised
182 if tgen
.routers_have_failure():
183 pytest
.skip(tgen
.errors
)
185 logger
.info("Checking OSPFv2 convergence on router r1")
187 router
= tgen
.gears
["r1"]
188 reffile
= os
.path
.join(CWD
, "r1/ospf_neighbor.json")
189 expected
= json
.loads(open(reffile
).read())
191 test_func
= functools
.partial(
192 topotest
.router_json_cmp
, router
, "show ip ospf neighbor json", expected
194 _
, res
= topotest
.run_and_expect(test_func
, None, count
=60, wait
=2)
195 assertmsg
= "OSPF router R1 did not converge"
196 assert res
is None, assertmsg
199 def test_pim_convergence():
200 "Test for PIM convergence"
203 # Skip if previous fatal error condition is raised
204 if tgen
.routers_have_failure():
205 pytest
.skip(tgen
.errors
)
207 logger
.info("Checking PIM convergence on router r1")
209 router
= tgen
.gears
["r1"]
210 reffile
= os
.path
.join(CWD
, "r1/pim_neighbor.json")
211 expected
= json
.loads(open(reffile
).read())
213 test_func
= functools
.partial(
214 topotest
.router_json_cmp
, router
, "show ip pim neighbor json", expected
216 _
, res
= topotest
.run_and_expect(test_func
, None, count
=60, wait
=2)
217 assertmsg
= "PIM router R1 did not converge"
218 assert res
is None, assertmsg
221 def check_mcast_entry(entry
, mcastaddr
, pimrp
):
222 "Helper function to check RP"
226 "Testing PIM RP selection for ACL {} entry using {}".format(entry
, mcastaddr
)
229 with
McastTesterHelper(tgen
) as helper
:
230 helper
.run("h2", ["--send=0.7", mcastaddr
, "h2-eth0"])
231 helper
.run("h1", [mcastaddr
, "h1-eth0"])
233 logger
.info("mcast join and source for {} started".format(mcastaddr
))
237 router
= tgen
.gears
["r1"]
238 reffile
= os
.path
.join(CWD
, "r1/acl_{}_pim_join.json".format(entry
))
239 expected
= json
.loads(open(reffile
).read())
241 logger
.info("verifying pim join on r1 for {}".format(mcastaddr
))
242 test_func
= functools
.partial(
243 topotest
.router_json_cmp
, router
, "show ip pim join json", expected
245 _
, res
= topotest
.run_and_expect(test_func
, None, count
=60, wait
=2)
246 assertmsg
= "PIM router r1 did not show join status"
247 assert res
is None, assertmsg
249 logger
.info("verifying pim join on PIM RP {} for {}".format(pimrp
, mcastaddr
))
250 router
= tgen
.gears
[pimrp
]
251 reffile
= os
.path
.join(CWD
, "{}/acl_{}_pim_join.json".format(pimrp
, entry
))
252 expected
= json
.loads(open(reffile
).read())
254 test_func
= functools
.partial(
255 topotest
.router_json_cmp
, router
, "show ip pim join json", expected
257 _
, res
= topotest
.run_and_expect(test_func
, None, count
=60, wait
=2)
258 assertmsg
= "PIM router {} did not get selected as the PIM RP".format(pimrp
)
259 assert res
is None, assertmsg
264 def test_mcast_acl_1():
265 "Test 1st ACL entry 239.100.0.0/28 with 239.100.0.1"
268 # Skip if previous fatal error condition is raised
269 if tgen
.routers_have_failure():
270 pytest
.skip(tgen
.errors
)
272 check_mcast_entry(1, "239.100.0.1", "r11")
275 def test_mcast_acl_2():
276 "Test 2nd ACL entry 239.100.0.17/32 with 239.100.0.17"
279 # Skip if previous fatal error condition is raised
280 if tgen
.routers_have_failure():
281 pytest
.skip(tgen
.errors
)
283 check_mcast_entry(2, "239.100.0.17", "r12")
286 def test_mcast_acl_3():
287 "Test 3rd ACL entry 239.100.0.32/27 with 239.100.0.32"
290 # Skip if previous fatal error condition is raised
291 if tgen
.routers_have_failure():
292 pytest
.skip(tgen
.errors
)
294 check_mcast_entry(3, "239.100.0.32", "r13")
297 def test_mcast_acl_4():
298 "Test 4th ACL entry 239.100.0.128/25 with 239.100.0.255"
301 # Skip if previous fatal error condition is raised
302 if tgen
.routers_have_failure():
303 pytest
.skip(tgen
.errors
)
305 check_mcast_entry(4, "239.100.0.255", "r14")
308 def test_mcast_acl_5():
309 "Test 5th ACL entry 239.100.0.96/28 with 239.100.0.97"
312 # Skip if previous fatal error condition is raised
313 if tgen
.routers_have_failure():
314 pytest
.skip(tgen
.errors
)
316 check_mcast_entry(5, "239.100.0.97", "r14")
319 def test_mcast_acl_6():
320 "Test 6th ACL entry 239.100.0.64/28 with 239.100.0.70"
323 # Skip if previous fatal error condition is raised
324 if tgen
.routers_have_failure():
325 pytest
.skip(tgen
.errors
)
327 check_mcast_entry(6, "239.100.0.70", "r15")
330 if __name__
== "__main__":
331 args
= ["-s"] + sys
.argv
[1:]
332 sys
.exit(pytest
.main(args
))