]>
git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/config_timing/test_config_timing.py
3 # June 2 2021, Christian Hopps <chopps@labn.net>
5 # Copyright (c) 2021, LabN Consulting, L.L.C.
6 # Copyright (c) 2019-2020 by
7 # Donatas Abraitis <donatas.abraitis@gmail.com>
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
25 Test the timing of config operations.
27 The initial add of 10k routes is used as a baseline for timing and all future
28 operations are expected to complete in under 2 times that baseline. This is a
29 lot of slop; however, the pre-batching code some of these operations (e.g.,
30 adding the same set of 10k routes) would take 100 times longer, so the intention
31 is to catch those types of regressions.
42 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
43 sys
.path
.append(os
.path
.join(CWD
, "../"))
45 # pylint: disable=C0413
46 from lib
.topogen
import Topogen
, TopoRouter
, get_topogen
47 from lib
.topolog
import logger
49 pytestmark
= [pytest
.mark
.staticd
]
54 switch
= tgen
.add_switch("s1")
55 switch
.add_link(tgen
.gears
["r1"])
58 def setup_module(mod
):
59 tgen
= Topogen(build_topo
, mod
.__name
__)
62 router_list
= tgen
.routers()
63 for rname
, router
in router_list
.items():
66 os
.path
.join(CWD
, "{}/zebra.conf".format(rname
)),
69 TopoRouter
.RD_STATIC
, os
.path
.join(CWD
, "{}/staticd.conf".format(rname
))
75 def teardown_module(mod
):
80 def get_ip_networks(super_prefix
, base_count
, count
):
81 count_log2
= math
.log(base_count
, 2)
82 if count_log2
!= int(count_log2
):
83 count_log2
= int(count_log2
) + 1
85 count_log2
= int(count_log2
)
86 network
= ipaddress
.ip_network(super_prefix
)
87 return tuple(network
.subnets(count_log2
))[0:count
]
90 def test_static_timing():
93 if tgen
.routers_have_failure():
94 pytest
.skip(tgen
.errors
)
107 router_list
= tgen
.routers()
110 optype
= "adding" if add
else "removing"
111 iptype
= "IPv6" if do_ipv6
else "IPv4"
112 if super_prefix
is None:
113 super_prefix
= u
"2001::/48" if do_ipv6
else u
"10.0.0.0/8"
115 optyped
= "added" if add
else "removed"
117 for rname
, router
in router_list
.items():
118 router
.logger
.info("{} {} static {} routes".format(optype
, count
, iptype
))
120 # Generate config file.
121 config_file
= os
.path
.join(
122 router
.logdir
, rname
, "{}-routes-{}.conf".format(iptype
.lower(), optype
)
124 with
open(config_file
, "w") as f
:
125 for i
, net
in enumerate(get_ip_networks(super_prefix
, base_count
, count
)):
128 f
.write("ip route {} {} bad_input\n".format(net
, via
))
130 f
.write("no ip route {} {} bad_input\n".format(net
, via
))
132 f
.write("ip route {} {}\n".format(net
, via
))
134 f
.write("no ip route {} {}\n".format(net
, via
))
138 router
.vtysh_cmd("debug northbound callbacks configuration")
141 load_command
= 'vtysh -f "{}"'.format(config_file
)
142 tstamp
= datetime
.datetime
.now()
143 output
= router
.run(load_command
)
144 delta
= (datetime
.datetime
.now() - tstamp
).total_seconds()
148 "\nvtysh command => {}\nvtysh output <= {}\nin {}s".format(
149 load_command
, output
, delta
153 limit_delta
= base_delta
* d_multiplier
155 "{} {} {} static routes under {} in {}s (limit: {}s)".format(
156 optyped
, count
, iptype
.lower(), super_prefix
, tot_delta
, limit_delta
160 assert tot_delta
<= limit_delta
165 # Number of static routes
166 router
= tgen
.gears
["r1"]
167 output
= router
.run("vtysh -h | grep address-sanitizer")
169 logger
.info("No Address Sanitizer, generating 10000 routes")
172 logger
.info("Address Sanitizer build, only testing 50 routes")
176 [u
"10.0.0.0/8", u
"11.0.0.0/8"],
177 [u
"2100:1111:2220::/44", u
"2100:3333:4440::/44"],
181 for ipv6
in [False, True]:
182 base_delta
= do_config(
183 prefix_count
, prefix_count
, bad_indices
, 0, 0, True, ipv6
, prefix_base
[ipv6
][0]
186 # Another set of same number of prefixes
188 prefix_count
, prefix_count
, bad_indices
, base_delta
, 3, True, ipv6
, prefix_base
[ipv6
][1]
193 prefix_count
, prefix_count
, bad_indices
, base_delta
, 3, True, ipv6
, prefix_base
[ipv6
][0]
196 # Remove 1/2 of duplicate
205 prefix_base
[ipv6
][0],
208 # Add all back in so 1/2 replicate 1/2 new
210 prefix_count
, prefix_count
, bad_indices
, base_delta
, 3, True, ipv6
, prefix_base
[ipv6
][0]
215 prefix_count
, prefix_count
, bad_indices
, base_delta
, 3, False, ipv6
, prefix_base
[ipv6
][0]
218 prefix_count
, prefix_count
, bad_indices
, base_delta
, 3, False, ipv6
, prefix_base
[ipv6
][1]
222 if __name__
== "__main__":
223 args
= ["-s"] + sys
.argv
[1:]
224 sys
.exit(pytest
.main(args
))