]>
Commit | Line | Data |
---|---|---|
927b0802 | 1 | #!/usr/bin/env python |
acddc0ed | 2 | # SPDX-License-Identifier: ISC |
927b0802 OD |
3 | |
4 | # | |
5 | # test_ospf_te_topo1.py | |
6 | # Part of NetDEF Topology Tests | |
7 | # | |
8 | # Copyright (c) 2021 by Orange | |
9 | # Author: Olivier Dugeon <olivier.dugeon@orange.com> | |
10 | # | |
927b0802 OD |
11 | |
12 | """ | |
13 | test_ospf_te_topo1.py: Test the FRR OSPF with Traffic Engineering. | |
14 | ||
15 | +------------+ | |
16 | | | | |
17 | | R1 | | |
18 | | 10.0.225.1 | | |
19 | | | | |
20 | +------------+ | |
21 | r1-eth0| |r1-eth1 | |
22 | | | | |
23 | 10.0.0.0/24| |10.0.1.0/24 | |
24 | | | | |
25 | r2-eth0| |r2-eth1 | |
26 | +------------+ +------------+ | |
27 | | | | | | |
28 | | R2 |r2-eth2 r3-eth0| R3 | | |
29 | | 10.0.255.2 +------------------+ 10.0.255.3 | | |
30 | | | 10.0.3.0/24 | | | |
31 | +------------+ +------+-----+ | |
32 | r2-eth3| r3-eth1| | |
33 | | | | |
34 | 10.0.4.0/24| 10.0.5.0/24| | |
35 | | | | |
36 | r4-eth0| V | |
37 | +------------+ ASBR 10.0.255.5 | |
38 | | | | |
39 | | R4 | | |
40 | | 10.0.255.4 | | |
41 | | | | |
42 | +------------+ | |
43 | ||
44 | """ | |
45 | ||
46 | import os | |
47 | import sys | |
48 | import json | |
49 | from functools import partial | |
50 | ||
51 | # Save the Current Working Directory to find configuration files. | |
52 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
53 | sys.path.append(os.path.join(CWD, "../")) | |
54 | ||
55 | # pylint: disable=C0413 | |
56 | # Required to instantiate the topology builder class. | |
927b0802 OD |
57 | |
58 | # Import topogen and topotest helpers | |
59 | from lib import topotest | |
60 | from lib.topogen import Topogen, TopoRouter, get_topogen | |
61 | from lib.topolog import logger | |
62 | ||
63 | # and Finally pytest | |
64 | import pytest | |
65 | ||
66 | pytestmark = [pytest.mark.ospfd] | |
67 | ||
0b25370e | 68 | |
e82b531d CH |
69 | def build_topo(tgen): |
70 | "Build function" | |
927b0802 | 71 | |
e82b531d CH |
72 | # Create 4 routers |
73 | for routern in range(1, 5): | |
74 | tgen.add_router("r{}".format(routern)) | |
927b0802 | 75 | |
e82b531d CH |
76 | # Interconect router 1 and 2 with 2 links |
77 | switch = tgen.add_switch("s1") | |
78 | switch.add_link(tgen.gears["r1"]) | |
79 | switch.add_link(tgen.gears["r2"]) | |
80 | switch = tgen.add_switch("s2") | |
81 | switch.add_link(tgen.gears["r1"]) | |
82 | switch.add_link(tgen.gears["r2"]) | |
927b0802 | 83 | |
e82b531d CH |
84 | # Interconect router 3 and 2 |
85 | switch = tgen.add_switch("s3") | |
86 | switch.add_link(tgen.gears["r3"]) | |
87 | switch.add_link(tgen.gears["r2"]) | |
927b0802 | 88 | |
e82b531d CH |
89 | # Interconect router 4 and 2 |
90 | switch = tgen.add_switch("s4") | |
91 | switch.add_link(tgen.gears["r4"]) | |
92 | switch.add_link(tgen.gears["r2"]) | |
927b0802 | 93 | |
e82b531d CH |
94 | # Interconnect router 3 with next AS |
95 | switch = tgen.add_switch("s5") | |
96 | switch.add_link(tgen.gears["r3"]) | |
927b0802 OD |
97 | |
98 | ||
99 | def setup_module(mod): | |
100 | "Sets up the pytest environment" | |
101 | ||
102 | logger.info("\n\n---- Starting OSPF TE tests ----\n") | |
103 | ||
e82b531d | 104 | tgen = Topogen(build_topo, mod.__name__) |
927b0802 OD |
105 | tgen.start_topology() |
106 | ||
107 | router_list = tgen.routers() | |
108 | ||
109 | for rname, router in router_list.items(): | |
110 | router.load_config( | |
111 | TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) | |
112 | ) | |
113 | router.load_config( | |
114 | TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname)) | |
115 | ) | |
116 | ||
117 | # Initialize all routers. | |
118 | tgen.start_router() | |
119 | ||
120 | ||
121 | def teardown_module(): | |
122 | "Teardown the pytest environment" | |
123 | ||
124 | tgen = get_topogen() | |
125 | tgen.stop_topology() | |
126 | ||
127 | logger.info("\n\n---- OSPF TE tests End ----\n") | |
128 | ||
129 | ||
130 | def compare_ted_json_output(tgen, rname, fileref): | |
131 | "Compare TED JSON output" | |
132 | ||
133 | logger.info('Comparing router "%s" TED output', rname) | |
134 | ||
135 | filename = "{}/reference/{}".format(CWD, fileref) | |
136 | expected = json.loads(open(filename).read()) | |
137 | command = "show ip ospf mpls-te database json" | |
138 | ||
139 | # Run test function until we get an result. Wait at most 60 seconds. | |
140 | test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected) | |
141 | _, diff = topotest.run_and_expect(test_func, None, count=60, wait=2) | |
142 | assertmsg = '"{}" TED JSON output mismatches the expected result'.format(rname) | |
143 | assert diff is None, assertmsg | |
144 | ||
145 | ||
146 | def setup_testcase(msg): | |
147 | "Setup test case" | |
148 | ||
149 | logger.info(msg) | |
150 | tgen = get_topogen() | |
151 | ||
152 | # Skip if previous fatal error condition is raised | |
153 | if tgen.routers_have_failure(): | |
154 | pytest.skip(tgen.errors) | |
155 | ||
156 | return tgen | |
157 | ||
158 | ||
159 | # Note that all routers must discover the same Network Topology, so the same TED. | |
160 | ||
0b25370e | 161 | |
927b0802 OD |
162 | def test_step1(): |
163 | "Step1: Check initial topology" | |
164 | ||
165 | tgen = setup_testcase("Step1: test initial OSPF TE Data Base") | |
166 | ||
167 | for rname in ["r1", "r2", "r3", "r4"]: | |
168 | compare_ted_json_output(tgen, rname, "ted_step1.json") | |
169 | ||
170 | ||
171 | def test_step2(): | |
172 | "Step2: Shutdown interface between r1 and r2 and verify that \ | |
173 | corresponding Edges are removed from the TED on all routers " | |
174 | ||
175 | tgen = setup_testcase("Step2: Shutdown interface between r1 & r2") | |
176 | ||
0b25370e DS |
177 | tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth1" -c "shutdown"') |
178 | tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth1" -c "shutdown"') | |
927b0802 OD |
179 | |
180 | for rname in ["r1", "r2", "r3", "r4"]: | |
181 | compare_ted_json_output(tgen, rname, "ted_step2.json") | |
182 | ||
183 | ||
184 | def test_step3(): | |
185 | "Step3: Disable Inter-AS on r3 and verify that corresponding Edge and \ | |
186 | remote ASBR are removed from the TED on all routers" | |
187 | ||
188 | tgen = setup_testcase("Step3: Disable Inter-AS on r3") | |
189 | ||
0b25370e | 190 | tgen.net["r3"].cmd('vtysh -c "conf t" -c "router ospf" -c "no mpls-te inter-as"') |
927b0802 OD |
191 | for rname in ["r1", "r2", "r3", "r4"]: |
192 | compare_ted_json_output(tgen, rname, "ted_step3.json") | |
193 | ||
194 | ||
195 | def test_step4(): | |
196 | "Step4: Enable Segment Routing on r1 and r2 and verify that corresponding \ | |
197 | Edges are updated with Adjacency SID and Subnets with Prefix SID in the \ | |
198 | TED on all routers" | |
199 | ||
200 | tgen = setup_testcase("Step4: Enable Segment Routing on r1 & r2") | |
201 | ||
0b25370e | 202 | tgen.net["r1"].cmd('vtysh -c "conf t" -c "router ospf" -c "segment-routing on"') |
927b0802 OD |
203 | tgen.net["r1"].cmd( |
204 | 'vtysh -c "conf t" -c "router ospf" -c "segment-routing global-block 20000 23999"' | |
205 | ) | |
206 | tgen.net["r1"].cmd( | |
207 | 'vtysh -c "conf t" -c "router ospf" -c "segment-routing prefix 10.0.255.1/32 index 10"' | |
208 | ) | |
0b25370e | 209 | tgen.net["r2"].cmd('vtysh -c "conf t" -c "router ospf" -c "segment-routing on"') |
927b0802 OD |
210 | tgen.net["r2"].cmd( |
211 | 'vtysh -c "conf t" -c "router ospf" -c "segment-routing node-msd 16"' | |
212 | ) | |
213 | tgen.net["r2"].cmd( | |
d2e02cbf | 214 | 'vtysh -c "conf t" -c "router ospf" -c "segment-routing global-block 16000 23999 local-block 5000 6999"' |
927b0802 OD |
215 | ) |
216 | tgen.net["r2"].cmd( | |
217 | 'vtysh -c "conf t" -c "router ospf" -c "segment-routing prefix 10.0.255.2/32 index 20 explicit-null"' | |
218 | ) | |
219 | ||
220 | for rname in ["r1", "r2", "r3", "r4"]: | |
221 | compare_ted_json_output(tgen, rname, "ted_step4.json") | |
222 | ||
223 | ||
224 | def test_step5(): | |
225 | "Step5: Re-enable interface between r1 & r2 and verify that corresponding \ | |
226 | Edges are added in the TED on all routers" | |
227 | ||
228 | tgen = setup_testcase("Step5: Re-enable interface between r1 & r2") | |
229 | ||
0b25370e DS |
230 | tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth1" -c "no shutdown"') |
231 | tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth1" -c "no shutdown"') | |
927b0802 OD |
232 | |
233 | for rname in ["r1", "r2", "r3", "r4"]: | |
234 | compare_ted_json_output(tgen, rname, "ted_step5.json") | |
235 | ||
236 | ||
237 | def test_step6(): | |
238 | "Step6: Set delay and jitter for interface r4-eth0 on r4, remove use-bw \ | |
239 | for interface r2-eth3 on r2 and verify that corresponding Edges are \ | |
240 | updated in the TED on all routers" | |
241 | ||
242 | tgen = setup_testcase("Step6: Modify link parameters on r2 & r4") | |
243 | ||
244 | tgen.net["r2"].cmd( | |
245 | 'vtysh -c "conf t" -c "interface r2-eth3" -c "link-params" -c "no use-bw"' | |
246 | ) | |
247 | tgen.net["r4"].cmd( | |
248 | 'vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay 20000"' | |
249 | ) | |
250 | tgen.net["r4"].cmd( | |
251 | 'vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay-variation 10000"' | |
252 | ) | |
253 | ||
254 | for rname in ["r1", "r2", "r3", "r4"]: | |
255 | compare_ted_json_output(tgen, rname, "ted_step6.json") | |
256 | ||
257 | ||
258 | def test_step7(): | |
259 | "Step7: Disable OSPF on r4 and verify that corresponding Vertex, Edges and \ | |
260 | Subnets are removed from the TED on all remaining routers" | |
261 | ||
262 | tgen = setup_testcase("Step7: Disable OSPF on r4") | |
263 | ||
0b25370e | 264 | tgen.net["r4"].cmd('vtysh -c "conf t" -c "no router ospf"') |
927b0802 OD |
265 | |
266 | for rname in ["r1", "r2", "r3"]: | |
267 | compare_ted_json_output(tgen, rname, "ted_step7.json") | |
268 | ||
269 | ||
270 | def test_memory_leak(): | |
271 | "Run the memory leak test and report results." | |
272 | ||
273 | tgen = get_topogen() | |
274 | if not tgen.is_memleak_enabled(): | |
275 | pytest.skip("Memory leak test/report is disabled") | |
276 | ||
277 | tgen.report_memory_leaks() | |
278 | ||
279 | ||
280 | if __name__ == "__main__": | |
281 | args = ["-s"] + sys.argv[1:] | |
282 | sys.exit(pytest.main(args)) |