]>
Commit | Line | Data |
---|---|---|
6fcaea2b RW |
1 | #!/usr/bin/env python |
2 | ||
3 | # | |
4 | # test_ldp_vpls_topo1.py | |
5 | # Part of NetDEF Topology Tests | |
6 | # | |
7 | # Copyright (c) 2017 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_ldp_vpls_topo1.py: | |
27 | ||
28 | +---------+ +---------+ | |
29 | | | | | | |
30 | | CE1 | | CE2 | | |
31 | | | | | | |
32 | +---------+ +---------+ | |
33 | ce1-eth0 (172.16.1.1/24)| |ce2-eth0 (172.16.1.2/24) | |
34 | | | | |
35 | | | | |
36 | rt1-eth0| |rt2-eth0 | |
37 | +---------+ 10.0.1.0/24 +---------+ | |
38 | | |rt1-eth1 | | | |
39 | | RT1 +----------------+ RT2 | | |
40 | | 1.1.1.1 | rt2-eth1| 2.2.2.2 | | |
41 | | | | | | |
42 | +---------+ +---------+ | |
43 | rt1-eth2| |rt2-eth2 | |
44 | | | | |
45 | | | | |
46 | 10.0.2.0/24| +---------+ |10.0.3.0/24 | |
47 | | | | | | |
48 | | | RT3 | | | |
49 | +--------+ 3.3.3.3 +-------+ | |
50 | rt3-eth2| |rt3-eth1 | |
51 | +---------+ | |
52 | |rt3-eth0 | |
53 | | | |
54 | | | |
55 | ce3-eth0 (172.16.1.3/24)| | |
56 | +---------+ | |
57 | | | | |
58 | | CE3 | | |
59 | | | | |
60 | +---------+ | |
61 | """ | |
62 | ||
63 | import os | |
64 | import sys | |
65 | import pytest | |
66 | import json | |
67 | from time import sleep | |
68 | from functools import partial | |
69 | ||
70 | # Save the Current Working Directory to find configuration files. | |
71 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
787e7624 | 72 | sys.path.append(os.path.join(CWD, "../")) |
6fcaea2b RW |
73 | |
74 | # pylint: disable=C0413 | |
75 | # Import topogen and topotest helpers | |
76 | from lib import topotest | |
77 | from lib.topogen import Topogen, TopoRouter, get_topogen | |
78 | from lib.topolog import logger | |
79 | ||
80 | # Required to instantiate the topology builder class. | |
81 | from mininet.topo import Topo | |
82 | ||
787e7624 | 83 | |
6fcaea2b RW |
84 | class TemplateTopo(Topo): |
85 | "Test topology builder" | |
787e7624 | 86 | |
6fcaea2b RW |
87 | def build(self, *_args, **_opts): |
88 | "Build function" | |
89 | tgen = get_topogen(self) | |
90 | ||
91 | # | |
92 | # Define FRR Routers | |
93 | # | |
787e7624 | 94 | for router in ["ce1", "ce2", "ce3", "r1", "r2", "r3"]: |
6fcaea2b RW |
95 | tgen.add_router(router) |
96 | ||
97 | # | |
98 | # Define connections | |
99 | # | |
787e7624 | 100 | switch = tgen.add_switch("s1") |
101 | switch.add_link(tgen.gears["ce1"]) | |
102 | switch.add_link(tgen.gears["r1"]) | |
103 | ||
104 | switch = tgen.add_switch("s2") | |
105 | switch.add_link(tgen.gears["ce2"]) | |
106 | switch.add_link(tgen.gears["r2"]) | |
6fcaea2b | 107 | |
787e7624 | 108 | switch = tgen.add_switch("s3") |
109 | switch.add_link(tgen.gears["ce3"]) | |
110 | switch.add_link(tgen.gears["r3"]) | |
6fcaea2b | 111 | |
787e7624 | 112 | switch = tgen.add_switch("s4") |
113 | switch.add_link(tgen.gears["r1"]) | |
114 | switch.add_link(tgen.gears["r2"]) | |
6fcaea2b | 115 | |
787e7624 | 116 | switch = tgen.add_switch("s5") |
117 | switch.add_link(tgen.gears["r1"]) | |
118 | switch.add_link(tgen.gears["r3"]) | |
6fcaea2b | 119 | |
787e7624 | 120 | switch = tgen.add_switch("s6") |
121 | switch.add_link(tgen.gears["r2"]) | |
122 | switch.add_link(tgen.gears["r3"]) | |
6fcaea2b | 123 | |
6fcaea2b RW |
124 | |
125 | def setup_module(mod): | |
126 | "Sets up the pytest environment" | |
127 | tgen = Topogen(TemplateTopo, mod.__name__) | |
128 | tgen.start_topology() | |
129 | ||
130 | router_list = tgen.routers() | |
131 | ||
132 | # For all registered routers, load the zebra configuration file | |
133 | for rname, router in router_list.iteritems(): | |
134 | router.load_config( | |
787e7624 | 135 | TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) |
6fcaea2b RW |
136 | ) |
137 | # Don't start ospfd and ldpd in the CE nodes | |
787e7624 | 138 | if router.name[0] == "r": |
6fcaea2b | 139 | router.load_config( |
787e7624 | 140 | TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname)) |
6fcaea2b RW |
141 | ) |
142 | router.load_config( | |
787e7624 | 143 | TopoRouter.RD_LDP, os.path.join(CWD, "{}/ldpd.conf".format(rname)) |
6fcaea2b RW |
144 | ) |
145 | ||
146 | tgen.start_router() | |
147 | ||
787e7624 | 148 | |
6fcaea2b RW |
149 | def teardown_module(mod): |
150 | "Teardown the pytest environment" | |
151 | tgen = get_topogen() | |
152 | ||
153 | # This function tears down the whole topology. | |
154 | tgen.stop_topology() | |
155 | ||
6fcaea2b RW |
156 | |
157 | def router_compare_json_output(rname, command, reference): | |
96984a17 RZ |
158 | "Compare router JSON output" |
159 | ||
6fcaea2b | 160 | logger.info('Comparing router "%s" "%s" output', rname, command) |
6fcaea2b | 161 | |
96984a17 | 162 | tgen = get_topogen() |
787e7624 | 163 | filename = "{}/{}/{}".format(CWD, rname, reference) |
96984a17 RZ |
164 | expected = json.loads(open(filename).read()) |
165 | ||
166 | # Run test function until we get an result. Wait at most 80 seconds. | |
787e7624 | 167 | test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected) |
96984a17 | 168 | _, diff = topotest.run_and_expect(test_func, None, count=160, wait=0.5) |
968afc28 RZ |
169 | assertmsg = '"{}" JSON output mismatches the expected result'.format(rname) |
170 | assert diff is None, assertmsg | |
6fcaea2b | 171 | |
787e7624 | 172 | |
6fcaea2b RW |
173 | def test_ospf_convergence(): |
174 | logger.info("Test: check OSPF adjacencies") | |
175 | tgen = get_topogen() | |
176 | ||
f13a242c RW |
177 | # Skip if previous fatal error condition is raised |
178 | if tgen.routers_have_failure(): | |
179 | pytest.skip(tgen.errors) | |
180 | ||
787e7624 | 181 | for rname in ["r1", "r2", "r3"]: |
182 | router_compare_json_output( | |
183 | rname, "show ip ospf neighbor json", "show_ip_ospf_neighbor.json" | |
184 | ) | |
185 | ||
6fcaea2b | 186 | |
6fcaea2b RW |
187 | def test_rib(): |
188 | logger.info("Test: verify RIB") | |
189 | tgen = get_topogen() | |
190 | ||
f13a242c RW |
191 | # Skip if previous fatal error condition is raised |
192 | if tgen.routers_have_failure(): | |
193 | pytest.skip(tgen.errors) | |
194 | ||
787e7624 | 195 | for rname in ["r1", "r2", "r3"]: |
6fcaea2b RW |
196 | router_compare_json_output(rname, "show ip route json", "show_ip_route.ref") |
197 | ||
787e7624 | 198 | |
6fcaea2b RW |
199 | def test_ldp_adjacencies(): |
200 | logger.info("Test: verify LDP adjacencies") | |
201 | tgen = get_topogen() | |
202 | ||
f13a242c RW |
203 | # Skip if previous fatal error condition is raised |
204 | if tgen.routers_have_failure(): | |
205 | pytest.skip(tgen.errors) | |
206 | ||
787e7624 | 207 | for rname in ["r1", "r2", "r3"]: |
208 | router_compare_json_output( | |
209 | rname, "show mpls ldp discovery json", "show_ldp_discovery.ref" | |
210 | ) | |
211 | ||
6fcaea2b | 212 | |
6fcaea2b RW |
213 | def test_ldp_neighbors(): |
214 | logger.info("Test: verify LDP neighbors") | |
215 | tgen = get_topogen() | |
216 | ||
f13a242c RW |
217 | # Skip if previous fatal error condition is raised |
218 | if tgen.routers_have_failure(): | |
219 | pytest.skip(tgen.errors) | |
220 | ||
787e7624 | 221 | for rname in ["r1", "r2", "r3"]: |
222 | router_compare_json_output( | |
223 | rname, "show mpls ldp neighbor json", "show_ldp_neighbor.ref" | |
224 | ) | |
225 | ||
6fcaea2b | 226 | |
6fcaea2b RW |
227 | def test_ldp_bindings(): |
228 | logger.info("Test: verify LDP bindings") | |
229 | tgen = get_topogen() | |
230 | ||
f13a242c RW |
231 | # Skip if previous fatal error condition is raised |
232 | if tgen.routers_have_failure(): | |
233 | pytest.skip(tgen.errors) | |
234 | ||
787e7624 | 235 | for rname in ["r1", "r2", "r3"]: |
236 | router_compare_json_output( | |
237 | rname, "show mpls ldp binding json", "show_ldp_binding.ref" | |
238 | ) | |
239 | ||
6fcaea2b | 240 | |
6fcaea2b RW |
241 | def test_ldp_pwid_bindings(): |
242 | logger.info("Test: verify LDP PW-ID bindings") | |
243 | tgen = get_topogen() | |
244 | ||
f13a242c RW |
245 | # Skip if previous fatal error condition is raised |
246 | if tgen.routers_have_failure(): | |
247 | pytest.skip(tgen.errors) | |
248 | ||
787e7624 | 249 | for rname in ["r1", "r2", "r3"]: |
250 | router_compare_json_output( | |
251 | rname, "show l2vpn atom binding json", "show_l2vpn_binding.ref" | |
252 | ) | |
253 | ||
6fcaea2b | 254 | |
6fcaea2b RW |
255 | def test_ldp_pseudowires(): |
256 | logger.info("Test: verify LDP pseudowires") | |
257 | tgen = get_topogen() | |
258 | ||
f13a242c RW |
259 | # Skip if previous fatal error condition is raised |
260 | if tgen.routers_have_failure(): | |
261 | pytest.skip(tgen.errors) | |
262 | ||
787e7624 | 263 | for rname in ["r1", "r2", "r3"]: |
264 | router_compare_json_output( | |
265 | rname, "show l2vpn atom vc json", "show_l2vpn_vc.ref" | |
266 | ) | |
267 | ||
6fcaea2b | 268 | |
6fcaea2b RW |
269 | def test_ldp_pseudowires_after_link_down(): |
270 | logger.info("Test: verify LDP pseudowires after r1-r2 link goes down") | |
271 | tgen = get_topogen() | |
272 | ||
f13a242c RW |
273 | # Skip if previous fatal error condition is raised |
274 | if tgen.routers_have_failure(): | |
275 | pytest.skip(tgen.errors) | |
276 | ||
6fcaea2b RW |
277 | # Shut down r1-r2 link */ |
278 | tgen = get_topogen() | |
787e7624 | 279 | tgen.gears["r1"].peer_link_enable("r1-eth1", False) |
c6d345e4 | 280 | topotest.sleep(5, "Waiting for the network to reconverge") |
6fcaea2b | 281 | |
6fcaea2b | 282 | # check if the pseudowire is still up (using an alternate path for nexthop resolution) |
787e7624 | 283 | for rname in ["r1", "r2", "r3"]: |
284 | router_compare_json_output( | |
285 | rname, "show l2vpn atom vc json", "show_l2vpn_vc.ref" | |
286 | ) | |
287 | ||
6fcaea2b RW |
288 | |
289 | # Memory leak test template | |
290 | def test_memory_leak(): | |
291 | "Run the memory leak test and report results." | |
292 | tgen = get_topogen() | |
293 | if not tgen.is_memleak_enabled(): | |
787e7624 | 294 | pytest.skip("Memory leak test/report is disabled") |
6fcaea2b RW |
295 | |
296 | tgen.report_memory_leaks() | |
297 | ||
787e7624 | 298 | |
299 | if __name__ == "__main__": | |
6fcaea2b RW |
300 | args = ["-s"] + sys.argv[1:] |
301 | sys.exit(pytest.main(args)) |