]>
Commit | Line | Data |
---|---|---|
be4d276c | 1 | #!/usr/bin/env python |
acddc0ed | 2 | # SPDX-License-Identifier: ISC |
be4d276c G |
3 | |
4 | # | |
5 | # test_ospf_tilfa_topo1.py | |
6 | # Part of NetDEF Topology Tests | |
7 | # | |
8 | # Copyright (c) 2020 by | |
9 | # Network Device Education Foundation, Inc. ("NetDEF") | |
10 | # | |
be4d276c G |
11 | |
12 | """ | |
13 | test_ospf_tilfa_topo1.py: | |
14 | ||
15 | This topology is intentionally kept simple, its main purpose is to verify that | |
16 | generated backup label stacks are inserted correctly into the RIB. For fancy | |
17 | topologies please use the unit test framework provided in `/tests/ospfd`. | |
18 | ||
19 | ||
20 | +---------+ +---------+ | |
21 | | | | | | |
22 | 10.0.1.0/24 eth+rt1| RT2 |eth+rt4 eth+rt2| RT2 | | |
23 | +---------------------+ 2.2.2.2 +---------------------+ 4.4.4.4 | | |
24 | | | | 10.0.3.0/24 | | | |
25 | |eth+rt2 +---------+ +---------+ | |
26 | +---------+ eth+rt5| | |
27 | | | | | |
28 | | RT1 | 10.0.5.0/24| | |
29 | | 1.1.1.1 | | | |
30 | | | | | |
31 | +---------+ eth+rt4| | |
32 | |eth+rt3 +---------+ +---------+ | |
33 | | | | 10.0.4.0/24 | | | |
34 | +---------------------+ RT3 +---------------------+ RT5 | | |
35 | 10.0.2.0/24 eth+rt1| 3.3.3.3 |eth+rt5 eth-rt3| 5.5.5.5 | | |
36 | | | | | | |
37 | +---------+ +---------+ | |
38 | """ | |
39 | ||
40 | import os | |
41 | import sys | |
42 | import pytest | |
43 | import json | |
be4d276c G |
44 | from functools import partial |
45 | ||
46 | # Save the Current Working Directory to find configuration files. | |
47 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
48 | sys.path.append(os.path.join(CWD, "../")) | |
49 | ||
50 | # pylint: disable=C0413 | |
51 | # Import topogen and topotest helpers | |
52 | from lib import topotest | |
53 | from lib.topogen import Topogen, TopoRouter, get_topogen | |
54 | from lib.topolog import logger | |
55 | ||
56 | # Required to instantiate the topology builder class. | |
be4d276c | 57 | |
6ff492b1 DS |
58 | pytestmark = [pytest.mark.ospfd] |
59 | ||
be4d276c | 60 | |
e82b531d CH |
61 | def build_topo(tgen): |
62 | "Build function" | |
be4d276c | 63 | |
e82b531d CH |
64 | # |
65 | # Define FRR Routers | |
66 | # | |
67 | for router in ["rt1", "rt2", "rt3", "rt4", "rt5"]: | |
68 | tgen.add_router(router) | |
be4d276c | 69 | |
e82b531d CH |
70 | # |
71 | # Define connections | |
72 | # | |
73 | switch = tgen.add_switch("s1") | |
74 | switch.add_link(tgen.gears["rt1"], nodeif="eth-rt2") | |
75 | switch.add_link(tgen.gears["rt2"], nodeif="eth-rt1") | |
be4d276c | 76 | |
e82b531d CH |
77 | switch = tgen.add_switch("s2") |
78 | switch.add_link(tgen.gears["rt1"], nodeif="eth-rt3") | |
79 | switch.add_link(tgen.gears["rt3"], nodeif="eth-rt1") | |
be4d276c | 80 | |
e82b531d CH |
81 | switch = tgen.add_switch("s3") |
82 | switch.add_link(tgen.gears["rt2"], nodeif="eth-rt4") | |
83 | switch.add_link(tgen.gears["rt4"], nodeif="eth-rt2") | |
be4d276c | 84 | |
e82b531d CH |
85 | switch = tgen.add_switch("s4") |
86 | switch.add_link(tgen.gears["rt3"], nodeif="eth-rt5") | |
87 | switch.add_link(tgen.gears["rt5"], nodeif="eth-rt3") | |
be4d276c | 88 | |
e82b531d CH |
89 | switch = tgen.add_switch("s5") |
90 | switch.add_link(tgen.gears["rt4"], nodeif="eth-rt5") | |
91 | switch.add_link(tgen.gears["rt5"], nodeif="eth-rt4") | |
be4d276c G |
92 | |
93 | ||
94 | def setup_module(mod): | |
95 | "Sets up the pytest environment" | |
e82b531d | 96 | tgen = Topogen(build_topo, mod.__name__) |
be4d276c G |
97 | tgen.start_topology() |
98 | ||
99 | router_list = tgen.routers() | |
100 | ||
101 | # For all registered routers, load the zebra configuration file | |
102 | for rname, router in router_list.items(): | |
103 | router.load_config( | |
104 | TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) | |
105 | ) | |
106 | router.load_config( | |
107 | TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname)) | |
108 | ) | |
109 | ||
110 | tgen.start_router() | |
111 | ||
112 | ||
113 | def teardown_module(mod): | |
114 | "Teardown the pytest environment" | |
115 | tgen = get_topogen() | |
116 | ||
117 | # This function tears down the whole topology. | |
118 | tgen.stop_topology() | |
119 | ||
120 | ||
121 | def router_compare_json_output(rname, command, reference): | |
122 | "Compare router JSON output" | |
123 | ||
124 | logger.info('Comparing router "%s" "%s" output', rname, command) | |
125 | ||
126 | tgen = get_topogen() | |
127 | filename = "{}/{}/{}".format(CWD, rname, reference) | |
128 | expected = json.loads(open(filename).read()) | |
129 | ||
130 | # Run test function until we get an result. Wait at most 60 seconds. | |
131 | test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected) | |
132 | _, diff = topotest.run_and_expect(test_func, None, count=120, wait=0.5) | |
133 | assertmsg = '"{}" JSON output mismatches the expected result'.format(rname) | |
134 | assert diff is None, assertmsg | |
135 | ||
136 | ||
137 | def test_ospf_initial_convergence_step1(): | |
138 | logger.info("Test (step 1): check initial convergence") | |
139 | tgen = get_topogen() | |
140 | ||
141 | # Skip if previous fatal error condition is raised | |
142 | if tgen.routers_have_failure(): | |
143 | pytest.skip(tgen.errors) | |
144 | ||
145 | router_compare_json_output( | |
146 | "rt1", | |
147 | "show ip route json", | |
148 | "step1/show_ip_route_initial.ref", | |
149 | ) | |
150 | ||
5980ad0a | 151 | |
be4d276c G |
152 | def test_ospf_link_protection_step2(): |
153 | logger.info("Test (step 2): check OSPF link protection") | |
154 | tgen = get_topogen() | |
155 | ||
156 | # Skip if previous fatal error condition is raised | |
157 | if tgen.routers_have_failure(): | |
158 | pytest.skip(tgen.errors) | |
159 | ||
160 | # enable TI-LFA link protection on all interfaces | |
5980ad0a | 161 | tgen.net["rt1"].cmd('vtysh -c "conf t" -c "router ospf" -c "fast-reroute ti-lfa"') |
be4d276c G |
162 | |
163 | router_compare_json_output( | |
164 | "rt1", | |
165 | "show ip route json", | |
166 | "step2/show_ip_route_link_protection.ref", | |
167 | ) | |
168 | ||
169 | # disable TI-LFA link protection on all interfaces | |
170 | tgen.net["rt1"].cmd( | |
171 | 'vtysh -c "conf t" -c "router ospf" -c "no fast-reroute ti-lfa"' | |
172 | ) | |
173 | ||
174 | # check if we got back to the initial route table | |
175 | router_compare_json_output( | |
176 | "rt1", | |
177 | "show ip route json", | |
178 | "step2/show_ip_route_initial.ref", | |
179 | ) | |
180 | ||
5980ad0a | 181 | |
be4d276c G |
182 | def test_ospf_node_protection_step3(): |
183 | logger.info("Test (step 3): check OSPF node protection") | |
184 | tgen = get_topogen() | |
185 | ||
186 | # Skip if previous fatal error condition is raised | |
187 | if tgen.routers_have_failure(): | |
188 | pytest.skip(tgen.errors) | |
189 | ||
190 | # enable TI-LFA node protection on all interfaces | |
191 | tgen.net["rt1"].cmd( | |
192 | 'vtysh -c "conf t" -c "router ospf" -c "fast-reroute ti-lfa node-protection"' | |
193 | ) | |
194 | ||
195 | router_compare_json_output( | |
196 | "rt1", | |
197 | "show ip route json", | |
198 | "step3/show_ip_route_node_protection.ref", | |
199 | ) | |
200 | ||
201 | # disable TI-LFA node protection on all interfaces | |
202 | tgen.net["rt1"].cmd( | |
203 | 'vtysh -c "conf t" -c "router ospf" -c "no fast-reroute ti-lfa node-protection"' | |
204 | ) | |
205 | ||
206 | # check if we got back to the initial route table | |
207 | router_compare_json_output( | |
208 | "rt1", | |
209 | "show ip route json", | |
210 | "step3/show_ip_route_initial.ref", | |
211 | ) | |
212 | ||
5980ad0a | 213 | |
be4d276c G |
214 | # Memory leak test template |
215 | def test_memory_leak(): | |
216 | "Run the memory leak test and report results." | |
217 | tgen = get_topogen() | |
218 | if not tgen.is_memleak_enabled(): | |
219 | pytest.skip("Memory leak test/report is disabled") | |
220 | ||
221 | tgen.report_memory_leaks() | |
222 | ||
5980ad0a | 223 | |
be4d276c G |
224 | if __name__ == "__main__": |
225 | args = ["-s"] + sys.argv[1:] | |
226 | sys.exit(pytest.main(args)) |