]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/isis_snmp/test_isis_snmp.py
Merge pull request #9219 from mobash-rasool/ospfv2-bug-fixes
[mirror_frr.git] / tests / topotests / isis_snmp / test_isis_snmp.py
1 #!/usr/bin/env python
2
3 #
4 # test_isis_snmp.py
5 # Part of NetDEF Topology Tests
6 #
7 # Copyright (c) 2020 by Volta Networks
8 #
9 # Permission to use, copy, modify, and/or distribute this software
10 # for any purpose with or without fee is hereby granted, provided
11 # that the above copyright notice and this permission notice appear
12 # in all copies.
13 #
14 # THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
15 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
17 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
18 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
20 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21 # OF THIS SOFTWARE.
22 #
23
24 """
25 test_isis_snmp.py:
26
27 +---------+ 45.0.0.0/24 +---------+
28 | | rt4-eth1 | |
29 | RT4 +----------------+ RT5 |
30 | | rt5-eth1| |
31 +---------+ +---------+
32 rt4-eth0| |rt5-eth0
33 | |
34 14.0.0.0/24| |25.0.0.0/24
35 | |
36 rt1-eth0| |rt2-eth0
37 +---------+ +---------+
38 | | | |
39 | RT1 | | RT2 |
40 | 1.1.1.1 | | 2.2.2.2 |
41 | | | |
42 +---------+ +---------+
43 rt1-eth1| |rt2-eth1
44 | |
45 | |
46 13.0.0.0/24| +---------+ |23.0.0.0/24
47 | | | |
48 | | RT3 | |
49 +--------+ 3.3.3.3 +-------+
50 rt3-eth1| |rt3-eth2
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 re
65 import sys
66 import pytest
67 import json
68 from time import sleep
69 from functools import partial
70
71 # Save the Current Working Directory to find configuration files.
72 CWD = os.path.dirname(os.path.realpath(__file__))
73 sys.path.append(os.path.join(CWD, "../"))
74
75 # pylint: disable=C0413
76 # Import topogen and topotest helpers
77 from lib import topotest
78 from lib.topogen import Topogen, TopoRouter, get_topogen
79 from lib.topolog import logger
80 from lib.snmptest import SnmpTester
81
82 # Required to instantiate the topology builder class.
83 from mininet.topo import Topo
84
85 pytestmark = [pytest.mark.isisd, pytest.mark.ldpd, pytest.mark.snmp]
86
87
88 class TemplateTopo(Topo):
89 "Test topology builder"
90
91 def build(self, *_args, **_opts):
92 "Build function"
93 tgen = get_topogen(self)
94
95 #
96 # Define FRR Routers
97 #
98 for router in ["ce3", "r1", "r2", "r3", "r4", "r5"]:
99 tgen.add_router(router)
100
101 #
102 # Define connections
103 #
104 switch = tgen.add_switch("s1")
105 switch.add_link(tgen.gears["r1"])
106 switch.add_link(tgen.gears["r4"])
107
108 switch = tgen.add_switch("s2")
109 switch.add_link(tgen.gears["r5"])
110 switch.add_link(tgen.gears["r2"])
111
112 switch = tgen.add_switch("s3")
113 switch.add_link(tgen.gears["ce3"])
114 switch.add_link(tgen.gears["r3"])
115
116 switch = tgen.add_switch("s4")
117 switch.add_link(tgen.gears["r4"])
118 switch.add_link(tgen.gears["r5"])
119
120 switch = tgen.add_switch("s5")
121 switch.add_link(tgen.gears["r1"])
122 switch.add_link(tgen.gears["r3"])
123
124 switch = tgen.add_switch("s6")
125 switch.add_link(tgen.gears["r2"])
126 switch.add_link(tgen.gears["r3"])
127
128
129 def setup_module(mod):
130 "Sets up the pytest environment"
131
132 # skip tests is SNMP not installed
133 if not os.path.isfile("/usr/sbin/snmpd"):
134 error_msg = "SNMP not installed - skipping"
135 pytest.skip(error_msg)
136
137 # This function initiates the topology build with Topogen...
138 tgen = Topogen(TemplateTopo, mod.__name__)
139 # ... and here it calls Mininet initialization functions.
140 tgen.start_topology()
141
142 router_list = tgen.routers()
143
144 # For all registered routers, load the zebra configuration file
145 for rname, router in router_list.iteritems():
146 router.load_config(
147 TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
148 )
149 # Don't start the following in the CE nodes
150 if router.name[0] == "r":
151 router.load_config(
152 TopoRouter.RD_ISIS,
153 os.path.join(CWD, "{}/isisd.conf".format(rname)),
154 "-M snmp",
155 )
156 router.load_config(
157 TopoRouter.RD_LDP,
158 os.path.join(CWD, "{}/ldpd.conf".format(rname)),
159 )
160 router.load_config(
161 TopoRouter.RD_SNMP,
162 os.path.join(CWD, "{}/snmpd.conf".format(rname)),
163 "-Le -Ivacm_conf,usmConf,iquery -V -DAgentX,trap",
164 )
165
166 # After loading the configurations, this function loads configured daemons.
167 tgen.start_router()
168
169
170 def teardown_module(mod):
171 "Teardown the pytest environment"
172 tgen = get_topogen()
173
174 # This function tears down the whole topology.
175 tgen.stop_topology()
176
177
178 def router_compare_json_output(rname, command, reference):
179 "Compare router JSON output"
180
181 logger.info('Comparing router "%s" "%s" output', rname, command)
182
183 tgen = get_topogen()
184 filename = "{}/{}/{}".format(CWD, rname, reference)
185 expected = json.loads(open(filename).read())
186
187 # Run test function until we get an result. Wait at most 80 seconds.
188 test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected)
189 _, diff = topotest.run_and_expect(test_func, None, count=160, wait=0.5)
190 assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
191 assert diff is None, assertmsg
192
193
194 def generate_oid(numoids, index1, index2):
195 if numoids == 1:
196 oid = "{}".format(index1)
197 else:
198 oid = "{}.{}".format(index1, index2)
199 return oid
200
201
202 def test_isis_convergence():
203 logger.info("Test: check ISIS adjacencies")
204 tgen = get_topogen()
205
206 for rname in ["r1", "r2", "r3", "r4", "r5"]:
207 router_compare_json_output(
208 rname,
209 "show yang operational-data /frr-interface:lib isisd",
210 "show_yang_interface_isis_adjacencies.ref",
211 )
212
213
214 def test_r1_scalar_snmp():
215 "Wait for protocol convergence"
216 tgen = get_topogen()
217
218 # Skip if previous fatal error condition is raised
219 if tgen.routers_have_failure():
220 pytest.skip(tgen.errors)
221
222 r1 = tgen.net.get("r1")
223 r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
224
225 assert r1_snmp.test_oid("isisSysVersion", "one(1)")
226 assert r1_snmp.test_oid("isisSysLevelType", "level1and2(3)")
227 assert r1_snmp.test_oid("isisSysID", "00 00 00 00 00 01")
228 assert r1_snmp.test_oid("isisSysMaxPathSplits", "32")
229 assert r1_snmp.test_oid("isisSysMaxLSPGenInt", "900 seconds")
230 assert r1_snmp.test_oid("isisSysAdminState", "on(1)")
231 assert r1_snmp.test_oid("isisSysMaxAge", "1200 seconds")
232 assert r1_snmp.test_oid("isisSysProtSupported", "07 5 6 7")
233
234 r2 = tgen.net.get("r2")
235 r2_snmp = SnmpTester(r2, "2.2.2.2", "public", "2c")
236
237 assert r2_snmp.test_oid("isisSysVersion", "one(1)")
238 assert r2_snmp.test_oid("isisSysLevelType", "level1and2(3)")
239 assert r2_snmp.test_oid("isisSysID", "00 00 00 00 00 02")
240 assert r2_snmp.test_oid("isisSysMaxPathSplits", "32")
241 assert r2_snmp.test_oid("isisSysMaxLSPGenInt", "900 seconds")
242 assert r2_snmp.test_oid("isisSysAdminState", "on(1)")
243 assert r2_snmp.test_oid("isisSysMaxAge", "1200 seconds")
244 assert r2_snmp.test_oid("isisSysProtSupported", "07 5 6 7")
245
246
247 circtable_test = {
248 "isisCircAdminState": ["on(1)", "on(1)"],
249 "isisCircExistState": ["active(1)", "active(1)"],
250 "isisCircType": ["broadcast(1)", "ptToPt(2)"],
251 "isisCircExtDomain": ["false(2)", "false(2)"],
252 "isisCircLevelType": ["level1(1)", "level1(1)"],
253 "isisCircPassiveCircuit": ["false(2)", "false(2)"],
254 "isisCircMeshGroupEnabled": ["inactive(1)", "inactive(1)"],
255 "isisCircSmallHellos": ["false(2)", "false(2)"],
256 "isisCirc3WayEnabled": ["false(2)", "false(2)"],
257 }
258
259
260 def test_r1_isisCircTable():
261 tgen = get_topogen()
262
263 r1 = tgen.net.get("r1")
264 r1r = tgen.gears["r1"]
265
266 r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
267
268 oids = []
269 oids.append(generate_oid(1, 1, 0))
270 oids.append(generate_oid(1, 2, 0))
271
272 # check items
273 for item in circtable_test.keys():
274 assertmsg = "{} should be {} oids {} full dict {}:".format(
275 item, circtable_test[item], oids, r1_snmp.walk(item)
276 )
277 assert r1_snmp.test_oid_walk(item, circtable_test[item], oids), assertmsg
278
279
280 circleveltable_test = {
281 "isisCircLevelMetric": ["10", "10"],
282 "isisCircLevelWideMetric": ["10", "10"],
283 "isisCircLevelISPriority": ["64", "64"],
284 "isisCircLevelHelloMultiplier": ["10", "10"],
285 "isisCircLevelHelloTimer": [
286 "3000 milliseconds",
287 "3000 milliseconds",
288 ],
289 "isisCircLevelMinLSPRetransInt": [
290 "1 seconds",
291 "1 seconds",
292 ],
293 }
294
295
296 def test_r1_isislevelCircTable():
297 tgen = get_topogen()
298
299 r1 = tgen.net.get("r1")
300 r1r = tgen.gears["r1"]
301
302 r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
303
304 oids = []
305 oids.append(generate_oid(2, 1, "area"))
306 oids.append(generate_oid(2, 2, "area"))
307
308 # check items
309 for item in circleveltable_test.keys():
310 assertmsg = "{} should be {} oids {} full dict {}:".format(
311 item, circleveltable_test[item], oids, r1_snmp.walk(item)
312 )
313 assert r1_snmp.test_oid_walk(item, circleveltable_test[item], oids), assertmsg
314
315
316 adjtable_test = {
317 "isisISAdjState": ["up(3)", "up(3)"],
318 "isisISAdj3WayState": ["down(2)", "up(0)"],
319 "isisISAdjNeighSysType": ["l1IntermediateSystem(1)", "l1IntermediateSystem(1)"],
320 "isisISAdjNeighSysID": ["00 00 00 00 00 04", "00 00 00 00 00 03"],
321 "isisISAdjUsage": ["0", "level1(1)"],
322 "isisISAdjNeighPriority": ["64", "0"],
323 }
324
325 adjtable_down_test = {
326 "isisISAdjState": ["up(3)"],
327 "isisISAdj3WayState": ["down(2)"],
328 "isisISAdjNeighSysType": ["l1IntermediateSystem(1)"],
329 "isisISAdjNeighSysID": ["00 00 00 00 00 04"],
330 "isisISAdjUsage": ["0"],
331 "isisISAdjNeighPriority": ["64"],
332 }
333
334
335 def test_r1_isisAdjTable():
336 "check ISIS Adjacency Table"
337 tgen = get_topogen()
338 r1 = tgen.net.get("r1")
339 r1_cmd = tgen.gears["r1"]
340 r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
341
342 oids = []
343 oids.append(generate_oid(2, 1, 1))
344 oids.append(generate_oid(2, 2, 1))
345
346 oids_down = []
347 oids_down.append(generate_oid(2, 1, 1))
348
349 # check items
350 for item in adjtable_test.keys():
351 assertmsg = "{} should be {} oids {} full dict {}:".format(
352 item, adjtable_test[item], oids, r1_snmp.walk(item)
353 )
354 assert r1_snmp.test_oid_walk(item, adjtable_test[item], oids), assertmsg
355
356 # shutdown interface and one adjacency should be removed
357 "check ISIS adjacency is removed when interface is shutdown"
358 r1_cmd.vtysh_cmd("conf t\ninterface r1-eth1\nshutdown")
359 r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
360
361 for item in adjtable_down_test.keys():
362 assertmsg = "{} should be {} oids {} full dict {}:".format(
363 item, adjtable_down_test[item], oids_down, r1_snmp.walk(item)
364 )
365 assert r1_snmp.test_oid_walk(
366 item, adjtable_down_test[item], oids_down
367 ), assertmsg
368
369 # no shutdown interface and adjacency should be restored
370 r1_cmd.vtysh_cmd("conf t\ninterface r1-eth1\nno shutdown")
371
372
373 # Memory leak test template
374 # disabling memory leak
375 def test_memory_leak():
376 "Run the memory leak test and report results."
377 tgen = get_topogen()
378 if not tgen.is_memleak_enabled():
379 pytest.skip("Memory leak test/report is disabled")
380
381 tgen.report_memory_leaks()
382
383
384 if __name__ == "__main__":
385 args = ["-s"] + sys.argv[1:]
386 sys.exit(pytest.main(args))