]>
Commit | Line | Data |
---|---|---|
4256a209 | 1 | #!/usr/bin/python |
2 | ||
3 | # | |
4 | # Copyright (c) 2020 by VMware, Inc. ("VMware") | |
5 | # Used Copyright (c) 2018 by Network Device Education Foundation, Inc. | |
6 | # ("NetDEF") in this file. | |
7 | # | |
8 | # Permission to use, copy, modify, and/or distribute this software | |
9 | # for any purpose with or without fee is hereby granted, provided | |
10 | # that the above copyright notice and this permission notice appear | |
11 | # in all copies. | |
12 | # | |
13 | # THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES | |
14 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
15 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR | |
16 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY | |
17 | # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
18 | # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS | |
19 | # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |
20 | # OF THIS SOFTWARE. | |
21 | # | |
22 | ||
23 | ||
24 | """OSPF Basic Functionality Automation.""" | |
25 | import ipaddress | |
26 | from lib.ospf import ( | |
27 | verify_ospf_neighbor, | |
28 | config_ospf_interface, | |
29 | clear_ospf, | |
30 | verify_ospf_rib, | |
31 | create_router_ospf, | |
32 | verify_ospf_interface, | |
33 | ) | |
34 | from lib.topojson import build_topo_from_json, build_config_from_json | |
35 | from lib.topolog import logger | |
36 | from lib.common_config import ( | |
37 | start_topology, | |
38 | write_test_header, | |
39 | write_test_footer, | |
40 | reset_config_on_routers, | |
41 | verify_rib, | |
42 | create_static_routes, | |
43 | step, | |
44 | create_route_maps, | |
45 | shutdown_bringup_interface, | |
46 | create_interfaces_cfg, | |
47 | ) | |
48 | from ipaddress import IPv4Address | |
49 | from lib.topogen import Topogen, get_topogen | |
50 | from mininet.topo import Topo | |
51 | import os | |
52 | import sys | |
53 | import time | |
54 | import pytest | |
55 | import json | |
4256a209 | 56 | |
57 | # Save the Current Working Directory to find configuration files. | |
58 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
59 | sys.path.append(os.path.join(CWD, "../")) | |
60 | sys.path.append(os.path.join(CWD, "../lib/")) | |
61 | # pylint: disable=C0413 | |
62 | # Import topogen and topotest helpers | |
63 | ||
64 | # Global variables | |
65 | topo = None | |
66 | # Reading the data from JSON File for topology creation | |
67 | jsonFile = "{}/ospf_nssa.json".format(CWD) | |
68 | try: | |
69 | with open(jsonFile, "r") as topoJson: | |
70 | topo = json.load(topoJson) | |
71 | except IOError: | |
72 | assert False, "Could not read file {}".format(jsonFile) | |
73 | NETWORK = { | |
74 | "ipv4": [ | |
75 | "11.0.20.1/32", | |
76 | "11.0.20.2/32", | |
77 | "11.0.20.3/32", | |
78 | "11.0.20.4/32", | |
79 | "11.0.20.5/32", | |
80 | ] | |
81 | } | |
82 | """ | |
83 | TOPOOLOGY = | |
84 | Please view in a fixed-width font such as Courier. | |
85 | +---+ A1 +---+ | |
86 | +R1 +------------+R2 | | |
87 | +-+-+- +--++ | |
88 | | -- -- | | |
89 | | -- A0 -- | | |
90 | A0| ---- | | |
91 | | ---- | A2 | |
92 | | -- -- | | |
93 | | -- -- | | |
94 | +-+-+- +-+-+ | |
95 | +R0 +-------------+R3 | | |
96 | +---+ A3 +---+ | |
97 | ||
98 | ||
99 | ||
100 | TESTCASES = | |
101 | 1. OSPF Learning - Verify OSPF can learn different types of LSA and | |
102 | processes them.[Edge learning different types of LSAs] | |
103 | 2. Verify that ospf non back bone area can be configured as NSSA area | |
104 | 3. Verify that ospf NSSA area DUT is capable receiving & processing | |
105 | Type7 N2 route. | |
106 | """ | |
107 | ||
108 | ||
109 | class CreateTopo(Topo): | |
110 | """ | |
111 | Test topology builder. | |
112 | ||
113 | * `Topo`: Topology object | |
114 | """ | |
115 | ||
116 | def build(self, *_args, **_opts): | |
117 | """Build function.""" | |
118 | tgen = get_topogen(self) | |
119 | ||
120 | # Building topology from json file | |
121 | build_topo_from_json(tgen, topo) | |
122 | ||
123 | ||
124 | def setup_module(mod): | |
125 | """ | |
126 | Sets up the pytest environment | |
127 | ||
128 | * `mod`: module name | |
129 | """ | |
130 | global topo | |
131 | testsuite_run_time = time.asctime(time.localtime(time.time())) | |
132 | logger.info("Testsuite start time: {}".format(testsuite_run_time)) | |
133 | logger.info("=" * 40) | |
134 | ||
135 | logger.info("Running setup_module to create topology") | |
136 | ||
137 | # This function initiates the topology build with Topogen... | |
138 | tgen = Topogen(CreateTopo, mod.__name__) | |
139 | # ... and here it calls Mininet initialization functions. | |
140 | ||
141 | # Starting topology, create tmp files which are loaded to routers | |
142 | # to start deamons and then start routers | |
143 | start_topology(tgen) | |
144 | # Creating configuration from JSON | |
145 | build_config_from_json(tgen, topo) | |
146 | ||
147 | # Don't run this test if we have any failure. | |
148 | if tgen.routers_have_failure(): | |
149 | pytest.skip(tgen.errors) | |
150 | # Api call verify whether OSPF is converged | |
151 | ospf_covergence = verify_ospf_neighbor(tgen, topo) | |
152 | assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( | |
153 | ospf_covergence | |
154 | ) | |
155 | ||
156 | logger.info("Running setup_module() done") | |
157 | ||
158 | ||
159 | def teardown_module(mod): | |
160 | """ | |
161 | Teardown the pytest environment. | |
162 | ||
163 | * `mod`: module name | |
164 | """ | |
165 | ||
166 | logger.info("Running teardown_module to delete topology") | |
167 | ||
168 | tgen = get_topogen() | |
169 | ||
170 | # Stop toplogy and Remove tmp files | |
171 | tgen.stop_topology() | |
172 | ||
173 | logger.info( | |
174 | "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) | |
175 | ) | |
176 | logger.info("=" * 40) | |
177 | ||
178 | ||
179 | def red_static(dut, config=True): | |
180 | """Local def for Redstribute static routes inside ospf.""" | |
181 | global topo | |
182 | tgen = get_topogen() | |
183 | if config: | |
184 | ospf_red = {dut: {"ospf": {"redistribute": [{"redist_type": "static"}]}}} | |
185 | else: | |
186 | ospf_red = { | |
187 | dut: {"ospf": {"redistribute": [{"redist_type": "static", "delete": True}]}} | |
188 | } | |
189 | result = create_router_ospf(tgen, topo, ospf_red) | |
190 | assert result is True, "Testcase : Failed \n Error: {}".format(result) | |
191 | ||
192 | ||
193 | def red_connected(dut, config=True): | |
194 | """Local def for Redstribute connected routes inside ospf.""" | |
195 | global topo | |
196 | tgen = get_topogen() | |
197 | if config: | |
198 | ospf_red = {dut: {"ospf": {"redistribute": [{"redist_type": "connected"}]}}} | |
199 | else: | |
200 | ospf_red = { | |
201 | dut: { | |
202 | "ospf": { | |
203 | "redistribute": [{"redist_type": "connected", "del_action": True}] | |
204 | } | |
205 | } | |
206 | } | |
207 | result = create_router_ospf(tgen, topo, ospf_red) | |
208 | assert result is True, "Testcase: Failed \n Error: {}".format(result) | |
209 | ||
210 | ||
211 | # ################################## | |
212 | # Test cases start here. | |
213 | # ################################## | |
214 | ||
215 | ||
216 | def test_ospf_learning_tc15_p0(request): | |
217 | """Verify OSPF can learn different types of LSA and processes them. | |
218 | ||
219 | OSPF Learning : Edge learning different types of LSAs. | |
220 | """ | |
221 | tc_name = request.node.name | |
222 | write_test_header(tc_name) | |
223 | tgen = get_topogen() | |
224 | ||
225 | # Don't run this test if we have any failure. | |
226 | if tgen.routers_have_failure(): | |
227 | pytest.skip(tgen.errors) | |
228 | ||
229 | global topo | |
230 | step("Bring up the base config as per the topology") | |
231 | step("Configure area 1 as NSSA Area") | |
232 | ||
233 | reset_config_on_routers(tgen) | |
234 | ||
235 | step("Verify that Type 3 summary LSA is originated for the same Area 0") | |
236 | ip = topo["routers"]["r1"]["links"]["r3-link0"]["ipv4"] | |
237 | ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network) | |
238 | ||
239 | dut = "r0" | |
240 | input_dict = { | |
241 | "r1": { | |
242 | "static_routes": [{"network": ip_net, "no_of_ip": 1, "routeType": "N IA"}] | |
243 | } | |
244 | } | |
245 | ||
246 | dut = "r0" | |
247 | result = verify_ospf_rib(tgen, dut, input_dict) | |
248 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
249 | ||
250 | protocol = "ospf" | |
251 | result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol) | |
252 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
253 | ||
254 | input_dict = { | |
255 | "r2": { | |
256 | "static_routes": [ | |
257 | {"network": NETWORK["ipv4"][0], "no_of_ip": 5, "next_hop": "Null0"} | |
258 | ] | |
259 | } | |
260 | } | |
261 | result = create_static_routes(tgen, input_dict) | |
262 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
263 | ||
264 | step("Redistribute static route in R2 ospf.") | |
265 | dut = "r2" | |
266 | red_static(dut) | |
267 | ||
268 | step("Verify that Type 5 LSA is originated by R2.") | |
269 | dut = "r0" | |
270 | protocol = "ospf" | |
271 | result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol) | |
272 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
273 | ||
274 | step("Verify that R0 receives Type 4 summary LSA.") | |
275 | dut = "r0" | |
276 | input_dict = { | |
277 | "r1": { | |
278 | "static_routes": [ | |
279 | {"network": NETWORK["ipv4"][0], "no_of_ip": 1, "routeType": "N E2"} | |
280 | ] | |
281 | } | |
282 | } | |
283 | ||
284 | dut = "r1" | |
285 | result = verify_ospf_rib(tgen, dut, input_dict) | |
286 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
287 | ||
288 | result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol) | |
289 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
290 | ||
291 | ospf_covergence = verify_ospf_neighbor(tgen, topo) | |
292 | assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( | |
293 | ospf_covergence | |
294 | ) | |
295 | ||
296 | step("Change area 1 as non nssa area (on the fly changing area" " type on DUT).") | |
297 | ||
298 | for rtr in ["r1", "r2", "r3"]: | |
299 | input_dict = { | |
300 | rtr: {"ospf": {"area": [{"id": "0.0.0.2", "type": "nssa", "delete": True}]}} | |
301 | } | |
302 | result = create_router_ospf(tgen, topo, input_dict) | |
303 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
304 | tc_name, result | |
305 | ) | |
306 | ||
307 | step("Verify that OSPF neighbours are reset after changing area type.") | |
308 | step("Verify that ABR R2 originates type 5 LSA in area 1.") | |
309 | step("Verify that route is calculated and installed in R1.") | |
310 | ||
311 | input_dict = { | |
312 | "r1": { | |
313 | "static_routes": [ | |
314 | {"network": NETWORK["ipv4"][0], "no_of_ip": 1, "routeType": "N E2"} | |
315 | ] | |
316 | } | |
317 | } | |
318 | ||
319 | dut = "r1" | |
320 | result = verify_ospf_rib(tgen, dut, input_dict) | |
321 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
322 | ||
323 | result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol) | |
324 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) | |
325 | ||
326 | write_test_footer(tc_name) | |
327 | ||
328 | ||
329 | if __name__ == "__main__": | |
330 | args = ["-s"] + sys.argv[1:] | |
331 | sys.exit(pytest.main(args)) |