]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/zebra_rib/test_zebra_rib.py
tests: Add pytest.mark.snmp
[mirror_frr.git] / tests / topotests / zebra_rib / test_zebra_rib.py
CommitLineData
abd2a1ff
DS
1#!/usr/bin/env python
2#
3# test_zebra_rib.py
4#
5# Copyright (c) 2019 by
6# Cumulus Networks, Inc
7# Donald Sharp
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_zebra_rib.py: Test some basic zebra <-> kernel interactions
26"""
27
28import os
29import re
30import sys
31from functools import partial
32import pytest
33import json
34
35# Save the Current Working Directory to find configuration files.
36CWD = os.path.dirname(os.path.realpath(__file__))
787e7624 37sys.path.append(os.path.join(CWD, "../"))
abd2a1ff
DS
38
39# pylint: disable=C0413
40# Import topogen and topotest helpers
41from lib import topotest
42from lib.topogen import Topogen, TopoRouter, get_topogen
43from lib.topolog import logger
fed16811 44from time import sleep
abd2a1ff
DS
45
46# Required to instantiate the topology builder class.
47from mininet.topo import Topo
48
787e7624 49
abd2a1ff
DS
50class ZebraTopo(Topo):
51 "Test topology builder"
787e7624 52
abd2a1ff
DS
53 def build(self, *_args, **_opts):
54 "Build function"
55 tgen = get_topogen(self)
56
787e7624 57 tgen.add_router("r1")
abd2a1ff
DS
58
59 # Create a empty network for router 1
787e7624 60 switch = tgen.add_switch("s1")
61 switch.add_link(tgen.gears["r1"])
62 switch.add_link(tgen.gears["r1"])
63 switch.add_link(tgen.gears["r1"])
64 switch.add_link(tgen.gears["r1"])
65 switch.add_link(tgen.gears["r1"])
66 switch.add_link(tgen.gears["r1"])
67 switch.add_link(tgen.gears["r1"])
68 switch.add_link(tgen.gears["r1"])
69
abd2a1ff
DS
70
71def setup_module(mod):
72 "Sets up the pytest environment"
73 tgen = Topogen(ZebraTopo, mod.__name__)
74 tgen.start_topology()
75
76 router_list = tgen.routers()
e5f0ed14 77 for rname, router in router_list.items():
abd2a1ff 78 router.load_config(
fed16811
DS
79 TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)))
80 router.load_config(
81 TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format(rname)))
abd2a1ff
DS
82
83 # Initialize all routers.
84 tgen.start_router()
85
787e7624 86
abd2a1ff
DS
87def teardown_module(mod):
88 "Teardown the pytest environment"
89 tgen = get_topogen()
90 tgen.stop_topology()
91
787e7624 92
abd2a1ff
DS
93def test_zebra_kernel_admin_distance():
94 "Test some basic kernel routes added that should be accepted"
95 logger.info("Test some basic kernel routes that should be accepted")
96 tgen = get_topogen()
97 if tgen.routers_have_failure():
787e7624 98 pytest.skip("skipped because of router(s) failure")
abd2a1ff 99
787e7624 100 r1 = tgen.gears["r1"]
abd2a1ff
DS
101
102 # Route with 255/8192 metric
787e7624 103 r1.run("ip route add 4.5.1.0/24 via 192.168.210.2 dev r1-eth0 metric 4278198272")
abd2a1ff 104 # Route with 1/1 metric
787e7624 105 r1.run("ip route add 4.5.2.0/24 via 192.168.211.2 dev r1-eth1 metric 16777217")
abd2a1ff 106 # Route with 10/1 metric
787e7624 107 r1.run("ip route add 4.5.3.0/24 via 192.168.212.2 dev r1-eth2 metric 167772161")
abd2a1ff 108 # Same route with a 160/1 metric
787e7624 109 r1.run("ip route add 4.5.3.0/24 via 192.168.213.2 dev r1-eth3 metric 2684354561")
abd2a1ff 110
787e7624 111 # Currently I believe we have a bug here with the same route and different
112 # metric. That needs to be properly resolved. Making a note for
113 # coming back around later and fixing this.
114 # tgen.mininet_cli()
abd2a1ff 115 for i in range(1, 2):
787e7624 116 json_file = "{}/r1/v4_route_{}.json".format(CWD, i)
abd2a1ff
DS
117 expected = json.loads(open(json_file).read())
118
787e7624 119 test_func = partial(
120 topotest.router_json_cmp,
121 r1,
122 "show ip route 4.5.{}.0 json".format(i),
123 expected,
124 )
125 _, result = topotest.run_and_expect(test_func, None, count=2, wait=0.5)
abd2a1ff
DS
126 assertmsg = '"r1" JSON output mismatches'
127 assert result is None, assertmsg
787e7624 128 # tgen.mininet_cli()
129
abd2a1ff
DS
130
131def test_zebra_kernel_override():
132 "Test that a FRR route with a lower admin distance takes over"
133 logger.info("Test kernel override with a better admin distance")
134 tgen = get_topogen()
787e7624 135 if tgen.routers_have_failure():
5094b56d 136 pytest.skip("skipped because of previous test failure")
abd2a1ff 137
787e7624 138 r1 = tgen.gears["r1"]
abd2a1ff 139 r1.vtysh_cmd("conf\nip route 4.5.1.0/24 192.168.216.3")
787e7624 140 json_file = "{}/r1/v4_route_1_static_override.json".format(CWD)
abd2a1ff
DS
141 expected = json.loads(open(json_file).read())
142
787e7624 143 test_func = partial(
144 topotest.router_json_cmp, r1, "show ip route 4.5.1.0 json", expected
145 )
146 _, result = topotest.run_and_expect(test_func, None, count=2, wait=0.5)
abd2a1ff
DS
147 assert result is None, '"r1" JSON output mismatches'
148
787e7624 149 logger.info(
150 "Test that the removal of the static route allows the kernel to take back over"
151 )
abd2a1ff 152 r1.vtysh_cmd("conf\nno ip route 4.5.1.0/24 192.168.216.3")
787e7624 153 json_file = "{}/r1/v4_route_1.json".format(CWD)
abd2a1ff
DS
154 expected = json.loads(open(json_file).read())
155
787e7624 156 test_func = partial(
157 topotest.router_json_cmp, r1, "show ip route 4.5.1.0 json", expected
158 )
159 _, result = topotest.run_and_expect(test_func, None, count=2, wait=0.5)
abd2a1ff
DS
160 assert result is None, '"r1" JSON output mismatches'
161
fed16811
DS
162def test_route_map_usage():
163 "Test that FRR only reruns over routes associated with the routemap"
164 logger.info("Test that FRR runs on selected re's on route-map changes")
165 tgen = get_topogen()
166 if tgen.routers_have_failure():
167 pytest.skip("Skipped because of previous test failure")
168
169 thisDir = os.path.dirname(os.path.realpath(__file__))
170
171 r1 = tgen.gears["r1"]
172 # set the delay timer to 1 to improve test coverage (HA)
173 r1.vtysh_cmd("conf\nzebra route-map delay-timer 1")
174 r1.vtysh_cmd("conf\nroute-map static permit 10\nset src 192.168.215.1")
175 r1.vtysh_cmd("conf\naccess-list 5 seq 5 permit 10.0.0.44/32")
176 r1.vtysh_cmd("conf\naccess-list 10 seq 5 permit 10.0.1.0/24")
177 r1.vtysh_cmd("conf\nroute-map sharp permit 10\nmatch ip address 10\nset src 192.168.214.1")
178 r1.vtysh_cmd("conf\nroute-map sharp permit 20\nset src 192.168.213.1")
179 r1.vtysh_cmd("conf\nip protocol static route-map static")
180 r1.vtysh_cmd("conf\nip protocol sharp route-map sharp")
181 sleep(4)
182 r1.vtysh_cmd("conf\nip route 10.100.100.100/32 192.168.216.3")
183 r1.vtysh_cmd("conf\nip route 10.100.100.101/32 10.0.0.44")
184 r1.vtysh_cmd("sharp install route 10.0.0.0 nexthop 192.168.216.3 500")
185 sleep(4)
186
187 static_rmapfile = "%s/r1/static_rmap.ref" % (thisDir)
188 expected = open(static_rmapfile).read().rstrip()
189 expected = ('\n'.join(expected.splitlines()) + '\n').rstrip()
190 actual = r1.vtysh_cmd("show route-map static")
191 actual = ('\n'.join(actual.splitlines()) + '\n').rstrip()
192 logger.info("Does the show route-map static command run the correct number of times")
193
194 diff = topotest.get_textdiff(actual, expected,
195 title1 = "Actual Route-map output",
196 title2 = "Expected Route-map output")
197 if diff:
198 logger.info("Actual:")
199 logger.info(actual)
200 logger.info("Expected:")
201 logger.info(expected)
202 srun = r1.vtysh_cmd("show run")
203 srun = ('\n'.join(srun.splitlines()) + '\n').rstrip()
204 logger.info("Show run")
205 logger.info(srun)
206 assert 0, "r1 static route processing:\n"
207
208 sharp_rmapfile = "%s/r1/sharp_rmap.ref" % (thisDir)
209 expected = open(sharp_rmapfile).read().rstrip()
210 expected = ('\n'.join(expected.splitlines()) + '\n').rstrip()
211 actual = r1.vtysh_cmd("show route-map sharp")
212 actual = ('\n'.join(actual.splitlines()) + '\n').rstrip()
213 logger.info("Does the show route-map sharp command run the correct number of times")
214
215 diff = topotest.get_textdiff(actual, expected,
216 title1 = "Actual Route-map output",
217 title2 = "Expected Route-map output")
218 if diff:
219 logger.info("Actual:")
220 logger.info(actual)
221 logger.info("Expected:")
222 logger.info(expected)
223 srun = r1.vtysh_cmd("show run")
224 srun = ('\n'.join(srun.splitlines()) + '\n').rstrip()
225 logger.info("Show run:")
226 logger.info(srun)
227 assert 0, "r1 sharp route-map processing:\n"
228
229 logger.info("Add a extension to the static route-map to see the static route go away")
230 r1.vtysh_cmd("conf\nroute-map sharp deny 5\nmatch ip address 5")
231 sleep(2)
232 # we are only checking the kernel here as that this will give us the implied
233 # testing of both the route-map and staticd withdrawing the route
234 # let's spot check that the routes were installed correctly
235 # in the kernel
236 logger.info("Test that the routes installed are correct")
237 sharp_ipfile = "%s/r1/iproute.ref" % (thisDir)
238 expected = open(sharp_ipfile).read().rstrip()
239 expected = ('\n'.join(expected.splitlines()) + '\n').rstrip()
240 actual = r1.run("ip route show")
241 actual = ('\n'.join(actual.splitlines()) + '\n').rstrip()
242 actual = re.sub(r" nhid [0-9][0-9]", "", actual)
243 actual = re.sub(r" proto sharp", " proto XXXX", actual)
244 actual = re.sub(r" proto static", " proto XXXX", actual)
245 actual = re.sub(r" proto 194", " proto XXXX", actual)
246 actual = re.sub(r" proto 196", " proto XXXX", actual)
247 actual = re.sub(r" proto kernel", " proto XXXX", actual)
248 actual = re.sub(r" proto 2", " proto XXXX", actual)
249 # Some platforms have double spaces? Why??????
250 actual = re.sub(r" proto XXXX ", " proto XXXX ", actual)
251 actual = re.sub(r" metric", " metric", actual)
252 actual = re.sub(r" link ", " link ", actual)
253 diff = topotest.get_textdiff(actual, expected,
254 title1 = "Actual ip route show",
255 title2 = "Expected ip route show")
256
257 if diff:
258 logger.info("Actual:")
259 logger.info(actual)
260 logger.info("Expected:")
261 logger.info(expected)
262 srun = r1.vtysh_cmd("show run")
263 srun = ('\n'.join(srun.splitlines()) + '\n').rstrip()
264 logger.info("Show run:")
265 logger.info(srun)
266 assert 0, "r1 ip route show is not correct:"
abd2a1ff
DS
267
268def test_memory_leak():
269 "Run the memory leak test and report results."
270 tgen = get_topogen()
271 if not tgen.is_memleak_enabled():
787e7624 272 pytest.skip("Memory leak test/report is disabled")
abd2a1ff
DS
273
274 tgen.report_memory_leaks()
275
787e7624 276
277if __name__ == "__main__":
abd2a1ff
DS
278 args = ["-s"] + sys.argv[1:]
279 sys.exit(pytest.main(args))