]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/pim_basic/test_pim.py
Merge pull request #9958 from donaldsharp/all_protocol_nhg_replace
[mirror_frr.git] / tests / topotests / pim_basic / test_pim.py
1 #!/usr/bin/env python
2
3 #
4 # test_pim.py
5 #
6 # Copyright (c) 2018 Cumulus Networks, Inc.
7 # Donald Sharp
8 #
9 # Permission to use, copy, modify, and/or distribute this software
10 # for any purpose with or without fee is hereby granted, provided
11 # that the above copyright notice and this permission notice appear
12 # in all copies.
13 #
14 # THE SOFTWARE IS PROVIDED "AS IS" AND Cumulus Networks DISCLAIMS ALL WARRANTIES
15 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
17 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
18 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
20 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21 # OF THIS SOFTWARE.
22 #
23
24 """
25 test_pim.py: Test pim
26 """
27
28 import os
29 import sys
30 import pytest
31 import json
32 from functools import partial
33
34 pytestmark = pytest.mark.pimd
35
36 CWD = os.path.dirname(os.path.realpath(__file__))
37 sys.path.append(os.path.join(CWD, "../"))
38
39 # pylint: disable=C0413
40 from lib import topotest
41 from lib.topogen import Topogen, TopoRouter, get_topogen
42 from lib.topolog import logger
43
44
45 pytestmark = [pytest.mark.pimd]
46
47
48 def build_topo(tgen):
49 "Build function"
50
51 for routern in range(1, 4):
52 tgen.add_router("r{}".format(routern))
53
54 tgen.add_router("rp")
55
56 # rp ------ r1 -------- r2
57 # \
58 # --------- r3
59 # r1 -> .1
60 # r2 -> .2
61 # rp -> .3
62 # r3 -> .4
63 # loopback network is 10.254.0.X/32
64 #
65 # r1 <- sw1 -> r2
66 # r1-eth0 <-> r2-eth0
67 # 10.0.20.0/24
68 sw = tgen.add_switch("sw1")
69 sw.add_link(tgen.gears["r1"])
70 sw.add_link(tgen.gears["r2"])
71
72 # r1 <- sw2 -> rp
73 # r1-eth1 <-> rp-eth0
74 # 10.0.30.0/24
75 sw = tgen.add_switch("sw2")
76 sw.add_link(tgen.gears["r1"])
77 sw.add_link(tgen.gears["rp"])
78
79 # 10.0.40.0/24
80 sw = tgen.add_switch("sw3")
81 sw.add_link(tgen.gears["r1"])
82 sw.add_link(tgen.gears["r3"])
83
84
85 def setup_module(mod):
86 "Sets up the pytest environment"
87 tgen = Topogen(build_topo, mod.__name__)
88 tgen.start_topology()
89
90 # For all registered routers, load the zebra configuration file
91 for rname, router in tgen.routers().items():
92 router.load_config(
93 TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
94 )
95 router.load_config(
96 TopoRouter.RD_PIM, os.path.join(CWD, "{}/pimd.conf".format(rname))
97 )
98 router.load_config(
99 TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
100 )
101
102 # After loading the configurations, this function loads configured daemons.
103 tgen.start_router()
104 # tgen.mininet_cli()
105
106
107 def teardown_module(mod):
108 "Teardown the pytest environment"
109 tgen = get_topogen()
110
111 # This function tears down the whole topology.
112 tgen.stop_topology()
113
114
115 def test_pim_rp_setup():
116 "Ensure basic routing has come up and the rp has an outgoing interface"
117 # Ensure rp and r1 establish pim neighbor ship and bgp has come up
118 # Finally ensure that the rp has an outgoing interface on r1
119 tgen = get_topogen()
120
121 r1 = tgen.gears["r1"]
122 json_file = "{}/{}/rp-info.json".format(CWD, r1.name)
123 expected = json.loads(open(json_file).read())
124
125 test_func = partial(
126 topotest.router_json_cmp, r1, "show ip pim rp-info json", expected
127 )
128 _, result = topotest.run_and_expect(test_func, None, count=15, wait=5)
129 assertmsg = '"{}" JSON output mismatches'.format(r1.name)
130 assert result is None, assertmsg
131 # tgen.mininet_cli()
132
133
134 def test_pim_send_mcast_stream():
135 "Establish a Multicast stream from r2 -> r1 and then ensure S,G is created as appropriate"
136 logger.info("Establish a Mcast stream from r2->r1 and then ensure S,G created")
137
138 tgen = get_topogen()
139
140 if tgen.routers_have_failure():
141 pytest.skip(tgen.errors)
142
143 rp = tgen.gears["rp"]
144 r3 = tgen.gears["r3"]
145 r2 = tgen.gears["r2"]
146 r1 = tgen.gears["r1"]
147
148 # Let's establish a S,G stream from r2 -> r1
149 CWD = os.path.dirname(os.path.realpath(__file__))
150 r2.run(
151 "{}/mcast-tx.py --ttl 5 --count 5 --interval 10 229.1.1.1 r2-eth0 > /tmp/bar".format(
152 CWD
153 )
154 )
155 # And from r3 -> r1
156 r3.run(
157 "{}/mcast-tx.py --ttl 5 --count 5 --interval 10 229.1.1.1 r3-eth0 > /tmp/bar".format(
158 CWD
159 )
160 )
161
162 # Let's see that it shows up and we have established some basic state
163 out = r1.vtysh_cmd("show ip pim upstream json", isjson=True)
164 expected = {
165 "229.1.1.1": {
166 "10.0.20.2": {
167 "firstHopRouter": 1,
168 "joinState": "NotJoined",
169 "regState": "RegPrune",
170 "inboundInterface": "r1-eth0",
171 }
172 }
173 }
174
175 test_func = partial(
176 topotest.router_json_cmp, r1, "show ip pim upstream json", expected
177 )
178 _, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
179 assert result is None, "failed to converge pim"
180 # tgen.mininet_cli()
181
182
183 def test_pim_rp_sees_stream():
184 "Ensure that the RP sees the stream and has acted accordingly"
185 tgen = get_topogen()
186
187 rp = tgen.gears["rp"]
188 json_file = "{}/{}/upstream.json".format(CWD, rp.name)
189 expected = json.loads(open(json_file).read())
190
191 test_func = partial(
192 topotest.router_json_cmp, rp, "show ip pim upstream json", expected
193 )
194 _, result = topotest.run_and_expect(test_func, None, count=20, wait=0.5)
195 assertmsg = '"{}" JSON output mismatches'.format(rp.name)
196 assert result is None, assertmsg
197
198
199 def test_pim_igmp_report():
200 "Send a igmp report from r2->r1 and ensure that the *,G state is created on r1"
201 logger.info("Send a igmp report from r2-r1 and ensure *,G created")
202
203 tgen = get_topogen()
204
205 if tgen.routers_have_failure():
206 pytest.skip(tgen.errors)
207
208 r2 = tgen.gears["r2"]
209 r1 = tgen.gears["r1"]
210
211 # Let's send a igmp report from r2->r1
212 cmd = [os.path.join(CWD, "mcast-rx.py"), "229.1.1.2", "r2-eth0"]
213 p = r2.popen(cmd)
214 try:
215 expected = {
216 "229.1.1.2": {
217 "*": {
218 "sourceIgmp": 1,
219 "joinState": "Joined",
220 "regState": "RegNoInfo",
221 "sptBit": 0,
222 }
223 }
224 }
225 test_func = partial(
226 topotest.router_json_cmp, r1, "show ip pim upstream json", expected
227 )
228 _, result = topotest.run_and_expect(test_func, None, count=5, wait=0.5)
229 assertmsg = '"{}" JSON output mismatches'.format(r1.name)
230 assert result is None, assertmsg
231 finally:
232 if p:
233 p.terminate()
234 p.wait()
235
236
237 def test_memory_leak():
238 "Run the memory leak test and report results."
239 tgen = get_topogen()
240 if not tgen.is_memleak_enabled():
241 pytest.skip("Memory leak test/report is disabled")
242
243 tgen.report_memory_leaks()
244
245
246 if __name__ == "__main__":
247 args = ["-s"] + sys.argv[1:]
248 sys.exit(pytest.main(args))