]> git.proxmox.com Git - mirror_frr.git/blame - 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
CommitLineData
0a434046 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"""
25test_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
63import os
0a434046 64import sys
65import pytest
66import json
0a434046 67from functools import partial
68
69# Save the Current Working Directory to find configuration files.
70CWD = os.path.dirname(os.path.realpath(__file__))
71sys.path.append(os.path.join(CWD, "../"))
72
73# pylint: disable=C0413
74# Import topogen and topotest helpers
75from lib import topotest
76from lib.topogen import Topogen, TopoRouter, get_topogen
77from lib.topolog import logger
78from lib.snmptest import SnmpTester
79
80# Required to instantiate the topology builder class.
0a434046 81
dbc5be82
DS
82pytestmark = [pytest.mark.isisd, pytest.mark.ldpd, pytest.mark.snmp]
83
0a434046 84
e82b531d
CH
85def build_topo(tgen):
86 "Build function"
0a434046 87
e82b531d
CH
88 #
89 # Define FRR Routers
90 #
91 for router in ["ce3", "r1", "r2", "r3", "r4", "r5"]:
92 tgen.add_router(router)
0a434046 93
e82b531d
CH
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"])
0a434046 100
e82b531d
CH
101 switch = tgen.add_switch("s2")
102 switch.add_link(tgen.gears["r5"])
103 switch.add_link(tgen.gears["r2"])
0a434046 104
e82b531d
CH
105 switch = tgen.add_switch("s3")
106 switch.add_link(tgen.gears["ce3"])
107 switch.add_link(tgen.gears["r3"])
0a434046 108
e82b531d
CH
109 switch = tgen.add_switch("s4")
110 switch.add_link(tgen.gears["r4"])
111 switch.add_link(tgen.gears["r5"])
0a434046 112
e82b531d
CH
113 switch = tgen.add_switch("s5")
114 switch.add_link(tgen.gears["r1"])
115 switch.add_link(tgen.gears["r3"])
0a434046 116
e82b531d
CH
117 switch = tgen.add_switch("s6")
118 switch.add_link(tgen.gears["r2"])
119 switch.add_link(tgen.gears["r3"])
0a434046 120
121
0a434046 122def 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...
e82b531d 131 tgen = Topogen(build_topo, mod.__name__)
0a434046 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
d7d21c3a 138 for rname, router in router_list.items():
0a434046 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(
0b25370e
DS
145 TopoRouter.RD_ISIS,
146 os.path.join(CWD, "{}/isisd.conf".format(rname)),
0a434046 147 "-M snmp",
148 )
149 router.load_config(
0b25370e
DS
150 TopoRouter.RD_LDP,
151 os.path.join(CWD, "{}/ldpd.conf".format(rname)),
0a434046 152 )
153 router.load_config(
0b25370e
DS
154 TopoRouter.RD_SNMP,
155 os.path.join(CWD, "{}/snmpd.conf".format(rname)),
0a434046 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
0b25370e 162
0a434046 163def 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
0b25370e 170
0a434046 171def 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
0b25370e 186
0a434046 187def 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
195def 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",
0b25370e
DS
203 "show_yang_interface_isis_adjacencies.ref",
204 )
205
0a434046 206
207def 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
8db751b8 215 r1 = tgen.gears["r1"]
0a434046 216 r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
217
0b25370e
DS
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")
0a434046 226
8db751b8 227 r2 = tgen.gears["r2"]
0a434046 228 r2_snmp = SnmpTester(r2, "2.2.2.2", "public", "2c")
0b25370e
DS
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")
0a434046 238
239
240circtable_test = {
bcf22081
IR
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)"],
0b25370e
DS
250}
251
0a434046 252
253def test_r1_isisCircTable():
254 tgen = get_topogen()
255
8db751b8 256 r1 = tgen.gears["r1"]
0a434046 257 r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
258
259 oids = []
0b25370e
DS
260 oids.append(generate_oid(1, 1, 0))
261 oids.append(generate_oid(1, 2, 0))
0a434046 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
0b25370e 270
0a434046 271circleveltable_test = {
bcf22081
IR
272 "isisCircLevelMetric": ["10", "10"],
273 "isisCircLevelWideMetric": ["10", "10"],
274 "isisCircLevelISPriority": ["64", "64"],
275 "isisCircLevelHelloMultiplier": ["10", "10"],
0b25370e
DS
276 "isisCircLevelHelloTimer": [
277 "3000 milliseconds",
278 "3000 milliseconds",
0b25370e
DS
279 ],
280 "isisCircLevelMinLSPRetransInt": [
281 "1 seconds",
282 "1 seconds",
0b25370e
DS
283 ],
284}
285
0a434046 286
287def test_r1_isislevelCircTable():
288 tgen = get_topogen()
289
8db751b8 290 r1 = tgen.gears["r1"]
0a434046 291 r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
292
293 oids = []
0b25370e
DS
294 oids.append(generate_oid(2, 1, "area"))
295 oids.append(generate_oid(2, 2, "area"))
0a434046 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
305adjtable_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"],
0a434046 310 "isisISAdjUsage": ["0", "level1(1)"],
311 "isisISAdjNeighPriority": ["64", "0"],
312}
313
314adjtable_down_test = {
315 "isisISAdjState": ["up(3)"],
316 "isisISAdj3WayState": ["down(2)"],
317 "isisISAdjNeighSysType": ["l1IntermediateSystem(1)"],
318 "isisISAdjNeighSysID": ["00 00 00 00 00 04"],
0a434046 319 "isisISAdjUsage": ["0"],
320 "isisISAdjNeighPriority": ["64"],
321}
322
0b25370e 323
0a434046 324def test_r1_isisAdjTable():
325 "check ISIS Adjacency Table"
326 tgen = get_topogen()
8db751b8 327 r1 = tgen.gears["r1"]
0a434046 328 r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
329
330 oids = []
0b25370e
DS
331 oids.append(generate_oid(2, 1, 1))
332 oids.append(generate_oid(2, 2, 1))
0a434046 333
334 oids_down = []
0b25370e 335 oids_down.append(generate_oid(2, 1, 1))
0a434046 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
0a434046 344 # shutdown interface and one adjacency should be removed
345 "check ISIS adjacency is removed when interface is shutdown"
8db751b8 346 r1.vtysh_cmd("conf t\ninterface r1-eth1\nshutdown")
0a434046 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 )
0b25370e
DS
353 assert r1_snmp.test_oid_walk(
354 item, adjtable_down_test[item], oids_down
355 ), assertmsg
0a434046 356
357 # no shutdown interface and adjacency should be restored
8db751b8 358 r1.vtysh_cmd("conf t\ninterface r1-eth1\nno shutdown")
0a434046 359
360
361# Memory leak test template
362# disabling memory leak
363def 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
372if __name__ == "__main__":
373 args = ["-s"] + sys.argv[1:]
374 sys.exit(pytest.main(args))