]>
Commit | Line | Data |
---|---|---|
be95145e OD |
1 | #!/usr/bin/env python |
2 | ||
3 | # | |
4 | # test_isis_te_topo1.py | |
5 | # Part of NetDEF Topology Tests | |
6 | # | |
7 | # Copyright (c) 2021 by Orange | |
8 | # Author: Olivier Dugeon <olivier.dugeon@orange.com> | |
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_isis_te_topo1.py: Test the FRR IS-IS with Traffic Engineering. | |
27 | ||
28 | +------------+ | |
29 | | | | |
30 | | R1 | | |
31 | | 10.0.225.1 | | |
32 | | | | |
33 | +------------+ | |
34 | r1-eth0| |r1-eth1 | |
35 | | | | |
36 | 10.0.0.0/24| |10.0.1.0/24 | |
37 | | |2001:db8:1:/64 | |
38 | | | | |
39 | r2-eth0| |r2-eth1 | |
40 | +------------+ +------------+ | |
41 | | | | | | |
42 | | R2 |r2-eth2 r3-eth0| R3 | | |
43 | | 10.0.255.2 +------------------+ 10.0.255.3 | | |
44 | | | 10.0.3.0/24 | | | |
45 | +------------+ 2001:db8:3:/64 +------+-----+ | |
46 | r2-eth3| r3-eth1| | |
47 | | | | |
48 | 10.0.4.0/24| | | |
49 | | | | |
50 | | | | |
51 | r4-eth0| 2001:db8:5:/64| | |
52 | +------------+ | | |
53 | | | | | |
54 | | R4 |r4-eth1 | | |
55 | | 10.0.255.4 +-------------------------+ | |
56 | | | | |
57 | +------------+ | |
58 | ||
59 | """ | |
60 | ||
61 | import os | |
62 | import sys | |
63 | import json | |
64 | from functools import partial | |
65 | ||
66 | # Save the Current Working Directory to find configuration files. | |
67 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
68 | sys.path.append(os.path.join(CWD, "../")) | |
69 | ||
70 | # pylint: disable=C0413 | |
71 | ||
72 | # Import topogen and topotest helpers | |
73 | from lib import topotest | |
74 | from lib.topogen import Topogen, TopoRouter, get_topogen | |
75 | from lib.topolog import logger | |
76 | ||
77 | # and Finally pytest | |
78 | import pytest | |
79 | ||
80 | pytestmark = [pytest.mark.isisd] | |
81 | ||
82 | ||
83 | def build_topo(tgen): | |
84 | "Build function" | |
85 | ||
86 | # Create 4 routers | |
87 | for routern in range(1, 5): | |
88 | tgen.add_router("r{}".format(routern)) | |
89 | ||
90 | # Interconect router 1 and 2 with 2 links | |
91 | switch = tgen.add_switch("s1") | |
92 | switch.add_link(tgen.gears["r1"]) | |
93 | switch.add_link(tgen.gears["r2"]) | |
94 | switch = tgen.add_switch("s2") | |
95 | switch.add_link(tgen.gears["r1"]) | |
96 | switch.add_link(tgen.gears["r2"]) | |
97 | ||
98 | # Interconect router 3 and 2 | |
99 | switch = tgen.add_switch("s3") | |
100 | switch.add_link(tgen.gears["r3"]) | |
101 | switch.add_link(tgen.gears["r2"]) | |
102 | ||
103 | # Interconect router 4 and 2 | |
104 | switch = tgen.add_switch("s4") | |
105 | switch.add_link(tgen.gears["r4"]) | |
106 | switch.add_link(tgen.gears["r2"]) | |
107 | ||
108 | # Interconnect router 3 and 4 | |
109 | switch = tgen.add_switch("s5") | |
110 | switch.add_link(tgen.gears["r3"]) | |
111 | switch.add_link(tgen.gears["r4"]) | |
112 | ||
113 | ||
114 | def setup_module(mod): | |
115 | "Sets up the pytest environment" | |
116 | ||
117 | logger.info("\n\n---- Starting IS-IS TE tests ----\n") | |
118 | ||
119 | tgen = Topogen(build_topo, mod.__name__) | |
120 | tgen.start_topology() | |
121 | ||
122 | router_list = tgen.routers() | |
123 | ||
124 | for rname, router in router_list.items(): | |
125 | router.load_config( | |
126 | TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) | |
127 | ) | |
128 | router.load_config( | |
129 | TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname)) | |
130 | ) | |
131 | ||
132 | # Initialize all routers. | |
133 | tgen.start_router() | |
134 | ||
135 | ||
136 | def teardown_module(): | |
137 | "Teardown the pytest environment" | |
138 | ||
139 | tgen = get_topogen() | |
140 | tgen.stop_topology() | |
141 | ||
142 | logger.info("\n\n---- IS-IS TE tests End ----\n") | |
143 | ||
144 | ||
145 | def compare_ted_json_output(tgen, rname, fileref): | |
146 | "Compare TED JSON output" | |
147 | ||
148 | logger.info('Comparing router "%s" TED output', rname) | |
149 | ||
150 | filename = "{}/reference/{}".format(CWD, fileref) | |
151 | expected = json.loads(open(filename).read()) | |
152 | command = "show isis mpls-te database json" | |
153 | ||
154 | # Run test function until we get an result. Wait at most 60 seconds. | |
155 | test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected) | |
156 | _, diff = topotest.run_and_expect(test_func, None, count=60, wait=2) | |
157 | assertmsg = '"{}" TED JSON output mismatches the expected result'.format(rname) | |
158 | assert diff is None, assertmsg | |
159 | ||
160 | ||
161 | def setup_testcase(msg): | |
162 | "Setup test case" | |
163 | ||
164 | logger.info(msg) | |
165 | tgen = get_topogen() | |
166 | ||
167 | # Skip if previous fatal error condition is raised | |
168 | if tgen.routers_have_failure(): | |
169 | pytest.skip(tgen.errors) | |
170 | ||
171 | return tgen | |
172 | ||
173 | ||
174 | # Note that all routers must discover the same Network Topology, so the same TED. | |
175 | ||
176 | ||
177 | def test_step1(): | |
178 | "Step1: Check initial topology" | |
179 | ||
180 | tgen = setup_testcase("Step1: test initial IS-IS TE Data Base") | |
181 | ||
182 | for rname in ["r1", "r2", "r3", "r4"]: | |
183 | compare_ted_json_output(tgen, rname, "ted_step1.json") | |
184 | ||
185 | ||
186 | def test_step2(): | |
187 | "Step2: Shutdown interface between r1 and r2 and verify that \ | |
188 | corresponding Edges are removed from the TED on all routers " | |
189 | ||
190 | tgen = setup_testcase("Step2: Shutdown interface between r1 & r2") | |
191 | ||
192 | tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth1" -c "shutdown"') | |
193 | tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth1" -c "shutdown"') | |
194 | ||
195 | for rname in ["r1", "r2", "r3", "r4"]: | |
196 | compare_ted_json_output(tgen, rname, "ted_step2.json") | |
197 | ||
198 | ||
199 | def test_step3(): | |
200 | "Step3: Enable IPv6 address between r1 and r2 and verify that \ | |
201 | corresponding Edges are added in the TED on all routers" | |
202 | ||
203 | tgen = setup_testcase("Step3: Add IPv6 on r1 and r2 interfaces") | |
204 | ||
205 | tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth0" -c "ipv6 address 2001:db8:0::1/64"') | |
206 | tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth0" -c "ipv6 router isis TE"') | |
207 | tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth0" -c "ipv6 address 2001:db8:0::2/64"') | |
208 | tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth0" -c "ipv6 router isis TE"') | |
209 | for rname in ["r1", "r2", "r3", "r4"]: | |
210 | compare_ted_json_output(tgen, rname, "ted_step3.json") | |
211 | ||
212 | ||
213 | def test_step4(): | |
214 | "Step4: Modify Segment Routing Prefix SID advertisement on Router r4" | |
215 | ||
216 | tgen = setup_testcase("Step4: Modify Prefix SID on router r4") | |
217 | ||
218 | tgen.net["r4"].cmd('vtysh -c "conf t" -c "router isis TE" -c "segment-routing prefix 10.0.255.4/32 index 40"') | |
219 | tgen.net["r4"].cmd('vtysh -c "conf t" -c "router isis TE" -c "segment-routing prefix 2001:db8:ffff::4/128 index 1040"') | |
220 | ||
221 | for rname in ["r1", "r2", "r3", "r4"]: | |
222 | compare_ted_json_output(tgen, rname, "ted_step4.json") | |
223 | ||
224 | ||
225 | def test_step5(): | |
226 | "Step5: Re-enable interface between r1 & r2 and verify that corresponding \ | |
227 | Edges are added in the TED on all routers" | |
228 | ||
229 | tgen = setup_testcase("Step5: Re-enable interface between r1 & r2") | |
230 | ||
231 | tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth1" -c "no shutdown"') | |
232 | tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth1" -c "no shutdown"') | |
233 | ||
234 | for rname in ["r1", "r2", "r3", "r4"]: | |
235 | compare_ted_json_output(tgen, rname, "ted_step5.json") | |
236 | ||
237 | ||
238 | def test_step6(): | |
239 | "Step6: Set delay and jitter for interface r4-eth0 on r4, remove use-bw \ | |
240 | for interface r2-eth3 on r2 and verify that corresponding Edges are \ | |
241 | updated in the TED on all routers" | |
242 | ||
243 | tgen = setup_testcase("Step6: Modify link parameters on r2 & r4") | |
244 | ||
245 | tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth3" -c "link-params" -c "no use-bw"') | |
246 | tgen.net["r4"].cmd('vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay 20000"') | |
247 | tgen.net["r4"].cmd('vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay-variation 10000"') | |
248 | ||
249 | for rname in ["r1", "r2", "r3", "r4"]: | |
250 | compare_ted_json_output(tgen, rname, "ted_step6.json") | |
251 | ||
252 | ||
7d46f8dd LS |
253 | def test_step7(): |
254 | "Step7: Set extended admin-group on r1-eth0" | |
255 | ||
256 | tgen = setup_testcase("Step7: Modify link parameters on r1") | |
257 | ||
258 | tgen.net["r1"].cmd('vtysh -c "conf t" -c "affinity-map WHITE bit-position 0"') | |
259 | tgen.net["r1"].cmd('vtysh -c "conf t" -c "affinity-map RED bit-position 31"') | |
260 | tgen.net["r1"].cmd('vtysh -c "conf t" -c "affinity-map GREEN bit-position 32"') | |
261 | tgen.net["r1"].cmd('vtysh -c "conf t" -c "affinity-map BLACK bit-position 128"') | |
262 | ||
263 | tgen.net["r1"].cmd( | |
264 | 'vtysh -c "conf t" -c "interface r1-eth0" -c "link-params" -c "affinity RED WHITE BLACK GREEN"' | |
265 | ) | |
266 | ||
267 | for rname in ["r1", "r2", "r3", "r4"]: | |
268 | compare_ted_json_output(tgen, rname, "ted_step7.json") | |
269 | ||
270 | ||
271 | def test_step8(): | |
272 | "Step8: Change value of affinity-map GREEN" | |
273 | ||
274 | tgen = setup_testcase("Step8: Change value of affinity-map GREEN") | |
275 | ||
276 | tgen.net["r1"].cmd('vtysh -c "conf t" -c "affinity-map GREEN bit-position 33"') | |
277 | ||
278 | for rname in ["r1", "r2", "r3", "r4"]: | |
279 | compare_ted_json_output(tgen, rname, "ted_step8.json") | |
280 | ||
281 | ||
282 | def test_step9(): | |
283 | "Step9: Trying to remove affinity-map GREEN. \ | |
284 | Must not succeed because in use" | |
285 | ||
286 | tgen = setup_testcase("Step9: Trying to remove affinity-map GREEN") | |
287 | ||
288 | tgen.net["r1"].cmd('vtysh -c "conf t" -c "no affinity-map GREEN"') | |
289 | ||
290 | for rname in ["r1", "r2", "r3", "r4"]: | |
291 | compare_ted_json_output(tgen, rname, "ted_step9.json") | |
292 | ||
293 | ||
294 | def test_step10(): | |
295 | "Step10: Removing r1-eth0 affinity GREEN" | |
296 | ||
297 | tgen = setup_testcase("Step10: Removing r1-eth0 affinity GREEN") | |
298 | ||
299 | tgen.net["r1"].cmd( | |
300 | 'vtysh -c "conf t" -c "interface r1-eth0" -c "link-params" -c "no affinity GREEN"' | |
301 | ) | |
302 | ||
303 | for rname in ["r1", "r2", "r3", "r4"]: | |
304 | compare_ted_json_output(tgen, rname, "ted_step10.json") | |
305 | ||
306 | ||
be95145e OD |
307 | def test_memory_leak(): |
308 | "Run the memory leak test and report results." | |
309 | ||
310 | tgen = get_topogen() | |
311 | if not tgen.is_memleak_enabled(): | |
312 | pytest.skip("Memory leak test/report is disabled") | |
313 | ||
314 | tgen.report_memory_leaks() | |
315 | ||
316 | ||
317 | if __name__ == "__main__": | |
318 | args = ["-s"] + sys.argv[1:] | |
319 | sys.exit(pytest.main(args)) |