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