]>
git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/pim_acl/test_pim_acl.py
5 # Part of NetDEF Topology Tests
7 # Copyright (c) 2020 by
8 # Network Device Education Foundation, Inc. ("NetDEF")
10 # Permission to use, copy, modify, and/or distribute this software
11 # for any purpose with or without fee is hereby granted, provided
12 # that the above copyright notice and this permission notice appear
15 # THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
16 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
18 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
19 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
21 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
26 test_pim_acl.py: Test PIM with RP selection using ACLs
29 # Test PIM RP selection with ACLs
31 # Testing RP selection with ACLs. R1 uses multiple ACLs
32 # to select desired RPs (R11 to R15)
36 # Create topology. Hosts are only using zebra/staticd,
37 # no PIM, no OSPF (using IGMPv2 for multicast)
38 # - test_ospf_convergence()
39 # Wait for OSPF convergence in each VRF. OSPF is run on
41 # - test_pim_convergence()
42 # Wait for PIM convergence on all routers. PIM is run on
44 # - test_mcast_acl_1():
45 # Test 1st ACL entry 239.100.0.0/28 with 239.100.0.1 which
46 # should use R11 as RP
47 # Stop multicast after verification
48 # - test_mcast_acl_2():
49 # Test 2nd ACL entry 239.100.0.17/32 with 239.100.0.17 which
50 # should use R12 as RP
51 # Stop multicast after verification
52 # - test_mcast_acl_3():
53 # Test 3rd ACL entry 239.100.0.32/27 with 239.100.0.32 which
54 # should use R13 as RP
55 # Stop multicast after verification
56 # - test_mcast_acl_4():
57 # Test 4th ACL entry 239.100.0.128/25 with 239.100.0.255 which
58 # should use R14 as RP
59 # Stop multicast after verification
60 # - test_mcast_acl_5():
61 # Test 5th ACL entry 239.100.0.96/28 with 239.100.0.97 which
62 # should use R14 as RP
63 # Stop multicast after verification
64 # - test_mcast_acl_6():
65 # Test 6th ACL entry 239.100.0.64/28 with 239.100.0.70 which
66 # should use R15 as RP
67 # Stop multicast after verification
72 # XXX clean up in later commit to avoid conflict on rebase
73 # pylint: disable=C0413
80 +-----------+ | +----------+
81 | | .1 | .11 | Host R11 |
82 +---------+ | R1 |---------+--------| PIM RP |
83 | Host H1 | 192.168.100.0/24 | | 192.168.101.0/24 +----------+
84 | receive |------------------| uses ACLs | | +----------+
85 |IGMP JOIN| .10 .1 | to pick | | .12 | Host R12 |
86 +---------+ | RP | +--------| PIM RP |
88 +-----------+ | +----------+
108 # Save the Current Working Directory to find configuration files.
109 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
110 sys
.path
.append(os
.path
.join(CWD
, "../"))
112 # pylint: disable=C0413
113 # Import topogen and topotest helpers
114 from lib
import topotest
115 from lib
.topogen
import Topogen
, TopoRouter
, get_topogen
116 from lib
.topolog
import logger
118 # Required to instantiate the topology builder class.
119 from lib
.pim
import McastTesterHelper
121 pytestmark
= [pytest
.mark
.pimd
, pytest
.mark
.ospfd
]
124 def build_topo(tgen
):
125 for hostNum
in range(1, 3):
126 tgen
.add_router("h{}".format(hostNum
))
128 # Create the main router
129 tgen
.add_router("r1")
131 # Create the PIM RP routers
132 for rtrNum
in range(11, 16):
133 tgen
.add_router("r{}".format(rtrNum
))
135 # Setup Switches and connections
136 for swNum
in range(1, 3):
137 tgen
.add_switch("sw{}".format(swNum
))
139 # Add connections H1 to R1 switch sw1
140 tgen
.gears
["h1"].add_link(tgen
.gears
["sw1"])
141 tgen
.gears
["r1"].add_link(tgen
.gears
["sw1"])
143 # Add connections R1 to R1x switch sw2
144 tgen
.gears
["r1"].add_link(tgen
.gears
["sw2"])
145 tgen
.gears
["h2"].add_link(tgen
.gears
["sw2"])
146 tgen
.gears
["r11"].add_link(tgen
.gears
["sw2"])
147 tgen
.gears
["r12"].add_link(tgen
.gears
["sw2"])
148 tgen
.gears
["r13"].add_link(tgen
.gears
["sw2"])
149 tgen
.gears
["r14"].add_link(tgen
.gears
["sw2"])
150 tgen
.gears
["r15"].add_link(tgen
.gears
["sw2"])
153 #####################################################
157 #####################################################
160 def setup_module(module
):
161 logger
.info("PIM RP ACL Topology: \n {}".format(TOPOLOGY
))
163 tgen
= Topogen(build_topo
, module
.__name
__)
164 tgen
.start_topology()
167 router_list
= tgen
.routers()
169 for rname
, router
in router_list
.items():
170 logger
.info("Loading router %s" % rname
)
172 TopoRouter
.RD_ZEBRA
, os
.path
.join(CWD
, "{}/zebra.conf".format(rname
))
175 # Only load ospf on routers, not on end hosts
177 TopoRouter
.RD_OSPF
, os
.path
.join(CWD
, "{}/ospfd.conf".format(rname
))
180 TopoRouter
.RD_PIM
, os
.path
.join(CWD
, "{}/pimd.conf".format(rname
))
185 def teardown_module(module
):
190 def test_ospf_convergence():
191 "Test for OSPFv2 convergence"
194 # Skip if previous fatal error condition is raised
195 if tgen
.routers_have_failure():
196 pytest
.skip(tgen
.errors
)
198 logger
.info("Checking OSPFv2 convergence on router r1")
200 router
= tgen
.gears
["r1"]
201 reffile
= os
.path
.join(CWD
, "r1/ospf_neighbor.json")
202 expected
= json
.loads(open(reffile
).read())
204 test_func
= functools
.partial(
205 topotest
.router_json_cmp
, router
, "show ip ospf neighbor json", expected
207 _
, res
= topotest
.run_and_expect(test_func
, None, count
=60, wait
=2)
208 assertmsg
= "OSPF router R1 did not converge"
209 assert res
is None, assertmsg
212 def test_pim_convergence():
213 "Test for PIM convergence"
216 # Skip if previous fatal error condition is raised
217 if tgen
.routers_have_failure():
218 pytest
.skip(tgen
.errors
)
220 logger
.info("Checking PIM convergence on router r1")
222 router
= tgen
.gears
["r1"]
223 reffile
= os
.path
.join(CWD
, "r1/pim_neighbor.json")
224 expected
= json
.loads(open(reffile
).read())
226 test_func
= functools
.partial(
227 topotest
.router_json_cmp
, router
, "show ip pim neighbor json", expected
229 _
, res
= topotest
.run_and_expect(test_func
, None, count
=60, wait
=2)
230 assertmsg
= "PIM router R1 did not converge"
231 assert res
is None, assertmsg
234 def check_mcast_entry(entry
, mcastaddr
, pimrp
):
235 "Helper function to check RP"
239 "Testing PIM RP selection for ACL {} entry using {}".format(entry
, mcastaddr
)
242 with
McastTesterHelper(tgen
) as helper
:
243 helper
.run("h2", ["--send=0.7", mcastaddr
, "h2-eth0"])
244 helper
.run("h1", [mcastaddr
, "h1-eth0"])
246 logger
.info("mcast join and source for {} started".format(mcastaddr
))
250 router
= tgen
.gears
["r1"]
251 reffile
= os
.path
.join(CWD
, "r1/acl_{}_pim_join.json".format(entry
))
252 expected
= json
.loads(open(reffile
).read())
254 logger
.info("verifying pim join on r1 for {}".format(mcastaddr
))
255 test_func
= functools
.partial(
256 topotest
.router_json_cmp
, router
, "show ip pim join json", expected
258 _
, res
= topotest
.run_and_expect(test_func
, None, count
=60, wait
=2)
259 assertmsg
= "PIM router r1 did not show join status"
260 assert res
is None, assertmsg
262 logger
.info("verifying pim join on PIM RP {} for {}".format(pimrp
, mcastaddr
))
263 router
= tgen
.gears
[pimrp
]
264 reffile
= os
.path
.join(CWD
, "{}/acl_{}_pim_join.json".format(pimrp
, entry
))
265 expected
= json
.loads(open(reffile
).read())
267 test_func
= functools
.partial(
268 topotest
.router_json_cmp
, router
, "show ip pim join json", expected
270 _
, res
= topotest
.run_and_expect(test_func
, None, count
=60, wait
=2)
271 assertmsg
= "PIM router {} did not get selected as the PIM RP".format(pimrp
)
272 assert res
is None, assertmsg
277 def test_mcast_acl_1():
278 "Test 1st ACL entry 239.100.0.0/28 with 239.100.0.1"
281 # Skip if previous fatal error condition is raised
282 if tgen
.routers_have_failure():
283 pytest
.skip(tgen
.errors
)
285 check_mcast_entry(1, "239.100.0.1", "r11")
288 def test_mcast_acl_2():
289 "Test 2nd ACL entry 239.100.0.17/32 with 239.100.0.17"
292 # Skip if previous fatal error condition is raised
293 if tgen
.routers_have_failure():
294 pytest
.skip(tgen
.errors
)
296 check_mcast_entry(2, "239.100.0.17", "r12")
299 def test_mcast_acl_3():
300 "Test 3rd ACL entry 239.100.0.32/27 with 239.100.0.32"
303 # Skip if previous fatal error condition is raised
304 if tgen
.routers_have_failure():
305 pytest
.skip(tgen
.errors
)
307 check_mcast_entry(3, "239.100.0.32", "r13")
310 def test_mcast_acl_4():
311 "Test 4th ACL entry 239.100.0.128/25 with 239.100.0.255"
314 # Skip if previous fatal error condition is raised
315 if tgen
.routers_have_failure():
316 pytest
.skip(tgen
.errors
)
318 check_mcast_entry(4, "239.100.0.255", "r14")
321 def test_mcast_acl_5():
322 "Test 5th ACL entry 239.100.0.96/28 with 239.100.0.97"
325 # Skip if previous fatal error condition is raised
326 if tgen
.routers_have_failure():
327 pytest
.skip(tgen
.errors
)
329 check_mcast_entry(5, "239.100.0.97", "r14")
332 def test_mcast_acl_6():
333 "Test 6th ACL entry 239.100.0.64/28 with 239.100.0.70"
336 # Skip if previous fatal error condition is raised
337 if tgen
.routers_have_failure():
338 pytest
.skip(tgen
.errors
)
340 check_mcast_entry(6, "239.100.0.70", "r15")
343 if __name__
== "__main__":
344 args
= ["-s"] + sys
.argv
[1:]
345 sys
.exit(pytest
.main(args
))