]>
Commit | Line | Data |
---|---|---|
0d00ac9c RZ |
1 | #!/usr/bin/env python |
2 | ||
3 | # | |
4 | # test_pim_basic_topo2.py | |
5 | # Part of NetDEF Topology Tests | |
6 | # | |
7 | # Copyright (c) 2021 by | |
8 | # Network Device Education Foundation, Inc. ("NetDEF") | |
9 | # | |
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 | |
13 | # in all copies. | |
14 | # | |
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 | |
22 | # OF THIS SOFTWARE. | |
23 | # | |
24 | ||
25 | """ | |
26 | test_pim_basic_topo2.py: Test the FRR PIM protocol convergence. | |
27 | """ | |
28 | ||
29 | import os | |
30 | import sys | |
31 | import json | |
32 | from functools import partial | |
33 | import pytest | |
34 | ||
35 | # Save the Current Working Directory to find configuration files. | |
36 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
37 | sys.path.append(os.path.join(CWD, "../")) | |
38 | ||
39 | # pylint: disable=C0413 | |
40 | # Import topogen and topotest helpers | |
41 | from lib import topotest | |
42 | from lib.topogen import Topogen, TopoRouter, get_topogen | |
43 | from lib.topolog import logger | |
44 | ||
45 | # Required to instantiate the topology builder class. | |
8db751b8 | 46 | from lib.micronet_compat import Topo |
0d00ac9c | 47 | |
d5f9847a | 48 | pytestmark = [pytest.mark.bfdd, pytest.mark.pimd] |
0d00ac9c RZ |
49 | |
50 | ||
51 | class PimBasicTopo2(Topo): | |
52 | "Test topology builder" | |
53 | ||
54 | def build(self, *_args, **_opts): | |
55 | "Build function" | |
56 | tgen = get_topogen(self) | |
57 | ||
58 | # Create 4 routers | |
59 | for routern in range(1, 5): | |
60 | tgen.add_router("r{}".format(routern)) | |
61 | ||
62 | switch = tgen.add_switch("s1") | |
63 | switch.add_link(tgen.gears["r1"]) | |
64 | switch.add_link(tgen.gears["r2"]) | |
65 | ||
66 | switch = tgen.add_switch("s2") | |
67 | switch.add_link(tgen.gears["r2"]) | |
68 | switch.add_link(tgen.gears["r3"]) | |
69 | ||
70 | switch = tgen.add_switch("s3") | |
71 | switch.add_link(tgen.gears["r2"]) | |
72 | switch.add_link(tgen.gears["r4"]) | |
73 | ||
74 | ||
75 | def setup_module(mod): | |
76 | "Sets up the pytest environment" | |
77 | tgen = Topogen(PimBasicTopo2, mod.__name__) | |
78 | tgen.start_topology() | |
79 | ||
80 | router_list = tgen.routers() | |
81 | for rname, router in router_list.items(): | |
82 | daemon_file = "{}/{}/bfdd.conf".format(CWD, rname) | |
83 | if os.path.isfile(daemon_file): | |
84 | router.load_config(TopoRouter.RD_BFD, daemon_file) | |
85 | ||
86 | daemon_file = "{}/{}/pimd.conf".format(CWD, rname) | |
87 | if os.path.isfile(daemon_file): | |
88 | router.load_config(TopoRouter.RD_PIM, daemon_file) | |
89 | ||
90 | daemon_file = "{}/{}/zebra.conf".format(CWD, rname) | |
91 | if os.path.isfile(daemon_file): | |
92 | router.load_config(TopoRouter.RD_ZEBRA, daemon_file) | |
93 | ||
94 | # Initialize all routers. | |
95 | tgen.start_router() | |
96 | ||
97 | ||
98 | def teardown_module(_mod): | |
99 | "Teardown the pytest environment" | |
100 | tgen = get_topogen() | |
101 | tgen.stop_topology() | |
102 | ||
103 | ||
104 | def expect_neighbor(router, interface, peer): | |
105 | "Wait until peer is present on interface." | |
106 | logger.info("waiting peer {} in {}".format(peer, interface)) | |
107 | tgen = get_topogen() | |
108 | test_func = partial( | |
109 | topotest.router_json_cmp, | |
110 | tgen.gears[router], | |
111 | "show ip pim neighbor json", | |
112 | {interface: {peer: {}}} | |
113 | ) | |
114 | _, result = topotest.run_and_expect(test_func, None, count=130, wait=1) | |
115 | assertmsg = '"{}" PIM convergence failure'.format(router) | |
116 | assert result is None, assertmsg | |
117 | ||
118 | ||
119 | def test_wait_pim_convergence(): | |
120 | "Wait for PIM to converge" | |
121 | tgen = get_topogen() | |
122 | if tgen.routers_have_failure(): | |
123 | pytest.skip(tgen.errors) | |
124 | ||
125 | logger.info("waiting for PIM to converge") | |
126 | ||
127 | expect_neighbor('r1', 'r1-eth0', '192.168.1.2') | |
128 | expect_neighbor('r2', 'r2-eth0', '192.168.1.1') | |
129 | ||
130 | expect_neighbor('r2', 'r2-eth1', '192.168.2.3') | |
131 | expect_neighbor('r2', 'r2-eth2', '192.168.3.4') | |
132 | ||
133 | expect_neighbor('r3', 'r3-eth0', '192.168.2.1') | |
134 | expect_neighbor('r4', 'r4-eth0', '192.168.3.1') | |
135 | ||
136 | ||
137 | def test_bfd_peers(): | |
138 | "Wait for BFD peers to show up." | |
139 | tgen = get_topogen() | |
140 | if tgen.routers_have_failure(): | |
141 | pytest.skip(tgen.errors) | |
142 | ||
143 | logger.info("waiting for BFD to converge") | |
144 | ||
145 | def expect_bfd_peer(router, peer): | |
146 | "Wait until peer is present on interface." | |
147 | logger.info("waiting BFD peer {} in {}".format(peer, router)) | |
148 | test_func = partial( | |
149 | topotest.router_json_cmp, | |
150 | tgen.gears[router], | |
151 | "show bfd peers json", | |
152 | [{"peer": peer, "status": "up"}] | |
153 | ) | |
154 | _, result = topotest.run_and_expect(test_func, None, count=10, wait=1) | |
155 | assertmsg = '"{}" BFD convergence failure'.format(router) | |
156 | assert result is None, assertmsg | |
157 | ||
158 | expect_bfd_peer("r1", "192.168.1.2") | |
159 | expect_bfd_peer("r2", "192.168.1.1") | |
160 | expect_bfd_peer("r2", "192.168.2.3") | |
161 | expect_bfd_peer("r2", "192.168.3.4") | |
162 | expect_bfd_peer("r3", "192.168.2.1") | |
163 | expect_bfd_peer("r4", "192.168.3.1") | |
164 | ||
165 | ||
166 | def test_pim_reconvergence(): | |
167 | "Disconnect a peer and expect it to disconnect." | |
168 | tgen = get_topogen() | |
169 | if tgen.routers_have_failure(): | |
170 | pytest.skip(tgen.errors) | |
171 | ||
172 | logger.info("waiting for disconnect convergence") | |
173 | tgen.gears["r4"].link_enable("r4-eth0", enabled=False) | |
174 | ||
175 | def expect_neighbor_down(router, interface, peer): | |
176 | "Wait until peer is present on interface." | |
177 | logger.info("waiting peer {} in {} to disappear".format(peer, interface)) | |
178 | test_func = partial( | |
179 | topotest.router_json_cmp, | |
180 | tgen.gears[router], | |
181 | "show ip pim neighbor json", | |
182 | {interface: {peer: None}} | |
183 | ) | |
184 | _, result = topotest.run_and_expect(test_func, None, count=4, wait=1) | |
185 | assertmsg = '"{}" PIM convergence failure'.format(router) | |
186 | assert result is None, assertmsg | |
187 | ||
188 | expect_neighbor_down("r2", "r2-eth2", "192.168.3.4") | |
189 | ||
190 | logger.info("waiting for reconvergence") | |
191 | tgen.gears["r4"].link_enable("r4-eth0", enabled=True) | |
192 | expect_neighbor("r2", "r2-eth2", "192.168.3.4") | |
193 | ||
194 | ||
d5f9847a RZ |
195 | def test_pim_bfd_profile(): |
196 | "Test that the BFD profile is properly applied in BFD." | |
197 | tgen = get_topogen() | |
198 | if tgen.routers_have_failure(): | |
199 | pytest.skip(tgen.errors) | |
200 | ||
201 | def expect_bfd_peer_settings(router, settings): | |
202 | "Expect the following BFD configuration" | |
203 | logger.info("Verifying BFD peer {} in {}".format(settings["peer"], router)) | |
204 | test_func = partial( | |
205 | topotest.router_json_cmp, | |
206 | tgen.gears[router], | |
207 | "show bfd peers json", | |
208 | [settings] | |
209 | ) | |
210 | _, result = topotest.run_and_expect(test_func, None, count=4, wait=1) | |
211 | assertmsg = '"{}" BFD convergence failure'.format(router) | |
212 | assert result is None, assertmsg | |
213 | ||
214 | expect_bfd_peer_settings("r1", { | |
215 | "peer": "192.168.1.2", | |
216 | "receive-interval": 250, | |
217 | "transmit-interval": 250, | |
218 | }) | |
219 | ||
220 | expect_bfd_peer_settings("r2", { | |
221 | "peer": "192.168.1.1", | |
222 | "remote-receive-interval": 250, | |
223 | "remote-transmit-interval": 250, | |
224 | }) | |
225 | ||
226 | ||
0d00ac9c RZ |
227 | def test_memory_leak(): |
228 | "Run the memory leak test and report results." | |
229 | tgen = get_topogen() | |
230 | if not tgen.is_memleak_enabled(): | |
231 | pytest.skip("Memory leak test/report is disabled") | |
232 | ||
233 | tgen.report_memory_leaks() | |
234 | ||
235 | ||
236 | if __name__ == "__main__": | |
237 | args = ["-s"] + sys.argv[1:] | |
238 | sys.exit(pytest.main(args)) |