]>
git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/isis_snmp/test_isis_snmp.py
5 # Part of NetDEF Topology Tests
7 # Copyright (c) 2020 by Volta Networks
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
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
27 +---------+ 45.0.0.0/24 +---------+
29 | RT4 +----------------+ RT5 |
31 +---------+ +---------+
34 14.0.0.0/24| |25.0.0.0/24
37 +---------+ +---------+
40 | 1.1.1.1 | | 2.2.2.2 |
42 +---------+ +---------+
46 13.0.0.0/24| +---------+ |23.0.0.0/24
49 +--------+ 3.3.3.3 +-------+
55 ce3-eth0 (172.16.1.3/24)|
68 from time
import sleep
69 from functools
import partial
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
, "../"))
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
82 # Required to instantiate the topology builder class.
83 from mininet
.topo
import Topo
86 class TemplateTopo(Topo
):
87 "Test topology builder"
89 def build(self
, *_args
, **_opts
):
91 tgen
= get_topogen(self
)
96 for router
in ["ce3", "r1", "r2", "r3", "r4", "r5"]:
97 tgen
.add_router(router
)
102 switch
= tgen
.add_switch("s1")
103 switch
.add_link(tgen
.gears
["r1"])
104 switch
.add_link(tgen
.gears
["r4"])
106 switch
= tgen
.add_switch("s2")
107 switch
.add_link(tgen
.gears
["r5"])
108 switch
.add_link(tgen
.gears
["r2"])
110 switch
= tgen
.add_switch("s3")
111 switch
.add_link(tgen
.gears
["ce3"])
112 switch
.add_link(tgen
.gears
["r3"])
114 switch
= tgen
.add_switch("s4")
115 switch
.add_link(tgen
.gears
["r4"])
116 switch
.add_link(tgen
.gears
["r5"])
118 switch
= tgen
.add_switch("s5")
119 switch
.add_link(tgen
.gears
["r1"])
120 switch
.add_link(tgen
.gears
["r3"])
122 switch
= tgen
.add_switch("s6")
123 switch
.add_link(tgen
.gears
["r2"])
124 switch
.add_link(tgen
.gears
["r3"])
127 def setup_module(mod
):
128 "Sets up the pytest environment"
130 # skip tests is SNMP not installed
131 if not os
.path
.isfile("/usr/sbin/snmpd"):
132 error_msg
= "SNMP not installed - skipping"
133 pytest
.skip(error_msg
)
135 # This function initiates the topology build with Topogen...
136 tgen
= Topogen(TemplateTopo
, mod
.__name
__)
137 # ... and here it calls Mininet initialization functions.
138 tgen
.start_topology()
140 router_list
= tgen
.routers()
142 # For all registered routers, load the zebra configuration file
143 for rname
, router
in router_list
.iteritems():
145 TopoRouter
.RD_ZEBRA
, os
.path
.join(CWD
, "{}/zebra.conf".format(rname
))
147 # Don't start the following in the CE nodes
148 if router
.name
[0] == "r":
151 os
.path
.join(CWD
, "{}/isisd.conf".format(rname
)),
156 os
.path
.join(CWD
, "{}/ldpd.conf".format(rname
)),
160 os
.path
.join(CWD
, "{}/snmpd.conf".format(rname
)),
161 "-Le -Ivacm_conf,usmConf,iquery -V -DAgentX,trap",
164 # After loading the configurations, this function loads configured daemons.
168 def teardown_module(mod
):
169 "Teardown the pytest environment"
172 # This function tears down the whole topology.
176 def router_compare_json_output(rname
, command
, reference
):
177 "Compare router JSON output"
179 logger
.info('Comparing router "%s" "%s" output', rname
, command
)
182 filename
= "{}/{}/{}".format(CWD
, rname
, reference
)
183 expected
= json
.loads(open(filename
).read())
185 # Run test function until we get an result. Wait at most 80 seconds.
186 test_func
= partial(topotest
.router_json_cmp
, tgen
.gears
[rname
], command
, expected
)
187 _
, diff
= topotest
.run_and_expect(test_func
, None, count
=160, wait
=0.5)
188 assertmsg
= '"{}" JSON output mismatches the expected result'.format(rname
)
189 assert diff
is None, assertmsg
192 def generate_oid(numoids
, index1
, index2
):
194 oid
= "{}".format(index1
)
196 oid
= "{}.{}".format(index1
, index2
)
200 def test_isis_convergence():
201 logger
.info("Test: check ISIS adjacencies")
204 for rname
in ["r1", "r2", "r3", "r4", "r5"]:
205 router_compare_json_output(
207 "show yang operational-data /frr-interface:lib isisd",
208 "show_yang_interface_isis_adjacencies.ref",
212 def test_r1_scalar_snmp():
213 "Wait for protocol convergence"
216 # Skip if previous fatal error condition is raised
217 if tgen
.routers_have_failure():
218 pytest
.skip(tgen
.errors
)
220 r1
= tgen
.net
.get("r1")
221 r1_snmp
= SnmpTester(r1
, "1.1.1.1", "public", "2c")
223 assert r1_snmp
.test_oid("isisSysVersion", "one(1)")
224 assert r1_snmp
.test_oid("isisSysLevelType", "level1and2(3)")
225 assert r1_snmp
.test_oid("isisSysID", "00 00 00 00 00 01")
226 assert r1_snmp
.test_oid("isisSysMaxPathSplits", "32")
227 assert r1_snmp
.test_oid("isisSysMaxLSPGenInt", "900 seconds")
228 assert r1_snmp
.test_oid("isisSysAdminState", "on(1)")
229 assert r1_snmp
.test_oid("isisSysMaxAge", "1200 seconds")
230 assert r1_snmp
.test_oid("isisSysProtSupported", "07 5 6 7")
232 r2
= tgen
.net
.get("r2")
233 r2_snmp
= SnmpTester(r2
, "2.2.2.2", "public", "2c")
235 assert r2_snmp
.test_oid("isisSysVersion", "one(1)")
236 assert r2_snmp
.test_oid("isisSysLevelType", "level1and2(3)")
237 assert r2_snmp
.test_oid("isisSysID", "00 00 00 00 00 02")
238 assert r2_snmp
.test_oid("isisSysMaxPathSplits", "32")
239 assert r2_snmp
.test_oid("isisSysMaxLSPGenInt", "900 seconds")
240 assert r2_snmp
.test_oid("isisSysAdminState", "on(1)")
241 assert r2_snmp
.test_oid("isisSysMaxAge", "1200 seconds")
242 assert r2_snmp
.test_oid("isisSysProtSupported", "07 5 6 7")
246 "isisCircAdminState": ["on(1)", "on(1)"],
247 "isisCircExistState": ["active(1)", "active(1)"],
248 "isisCircType": ["broadcast(1)", "ptToPt(2)"],
249 "isisCircExtDomain": ["false(2)", "false(2)"],
250 "isisCircLevelType": ["level1(1)", "level1(1)"],
251 "isisCircPassiveCircuit": ["false(2)", "false(2)"],
252 "isisCircMeshGroupEnabled": ["inactive(1)", "inactive(1)"],
253 "isisCircSmallHellos": ["false(2)", "false(2)"],
254 "isisCirc3WayEnabled": ["false(2)", "false(2)"],
258 def test_r1_isisCircTable():
261 r1
= tgen
.net
.get("r1")
262 r1r
= tgen
.gears
["r1"]
264 r1_snmp
= SnmpTester(r1
, "1.1.1.1", "public", "2c")
267 oids
.append(generate_oid(1, 1, 0))
268 oids
.append(generate_oid(1, 2, 0))
271 for item
in circtable_test
.keys():
272 assertmsg
= "{} should be {} oids {} full dict {}:".format(
273 item
, circtable_test
[item
], oids
, r1_snmp
.walk(item
)
275 assert r1_snmp
.test_oid_walk(item
, circtable_test
[item
], oids
), assertmsg
278 circleveltable_test
= {
279 "isisCircLevelMetric": ["10", "10"],
280 "isisCircLevelWideMetric": ["10", "10"],
281 "isisCircLevelISPriority": ["64", "64"],
282 "isisCircLevelHelloMultiplier": ["10", "10"],
283 "isisCircLevelHelloTimer": [
287 "isisCircLevelMinLSPRetransInt": [
294 def test_r1_isislevelCircTable():
297 r1
= tgen
.net
.get("r1")
298 r1r
= tgen
.gears
["r1"]
300 r1_snmp
= SnmpTester(r1
, "1.1.1.1", "public", "2c")
303 oids
.append(generate_oid(2, 1, "area"))
304 oids
.append(generate_oid(2, 2, "area"))
307 for item
in circleveltable_test
.keys():
308 assertmsg
= "{} should be {} oids {} full dict {}:".format(
309 item
, circleveltable_test
[item
], oids
, r1_snmp
.walk(item
)
311 assert r1_snmp
.test_oid_walk(item
, circleveltable_test
[item
], oids
), assertmsg
315 "isisISAdjState": ["up(3)", "up(3)"],
316 "isisISAdj3WayState": ["down(2)", "up(0)"],
317 "isisISAdjNeighSysType": ["l1IntermediateSystem(1)", "l1IntermediateSystem(1)"],
318 "isisISAdjNeighSysID": ["00 00 00 00 00 04", "00 00 00 00 00 03"],
319 "isisISAdjUsage": ["0", "level1(1)"],
320 "isisISAdjNeighPriority": ["64", "0"],
323 adjtable_down_test
= {
324 "isisISAdjState": ["up(3)"],
325 "isisISAdj3WayState": ["down(2)"],
326 "isisISAdjNeighSysType": ["l1IntermediateSystem(1)"],
327 "isisISAdjNeighSysID": ["00 00 00 00 00 04"],
328 "isisISAdjUsage": ["0"],
329 "isisISAdjNeighPriority": ["64"],
333 def test_r1_isisAdjTable():
334 "check ISIS Adjacency Table"
336 r1
= tgen
.net
.get("r1")
337 r1_cmd
= tgen
.gears
["r1"]
338 r1_snmp
= SnmpTester(r1
, "1.1.1.1", "public", "2c")
341 oids
.append(generate_oid(2, 1, 1))
342 oids
.append(generate_oid(2, 2, 1))
345 oids_down
.append(generate_oid(2, 1, 1))
348 for item
in adjtable_test
.keys():
349 assertmsg
= "{} should be {} oids {} full dict {}:".format(
350 item
, adjtable_test
[item
], oids
, r1_snmp
.walk(item
)
352 assert r1_snmp
.test_oid_walk(item
, adjtable_test
[item
], oids
), assertmsg
354 # shutdown interface and one adjacency should be removed
355 "check ISIS adjacency is removed when interface is shutdown"
356 r1_cmd
.vtysh_cmd("conf t\ninterface r1-eth1\nshutdown")
357 r1_snmp
= SnmpTester(r1
, "1.1.1.1", "public", "2c")
359 for item
in adjtable_down_test
.keys():
360 assertmsg
= "{} should be {} oids {} full dict {}:".format(
361 item
, adjtable_down_test
[item
], oids_down
, r1_snmp
.walk(item
)
363 assert r1_snmp
.test_oid_walk(
364 item
, adjtable_down_test
[item
], oids_down
367 # no shutdown interface and adjacency should be restored
368 r1_cmd
.vtysh_cmd("conf t\ninterface r1-eth1\nno shutdown")
371 # Memory leak test template
372 # disabling memory leak
373 def test_memory_leak():
374 "Run the memory leak test and report results."
376 if not tgen
.is_memleak_enabled():
377 pytest
.skip("Memory leak test/report is disabled")
379 tgen
.report_memory_leaks()
382 if __name__
== "__main__":
383 args
= ["-s"] + sys
.argv
[1:]
384 sys
.exit(pytest
.main(args
))