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