]>
git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/config_timing/test_config_timing.py
2 # SPDX-License-Identifier: ISC
4 # June 2 2021, Christian Hopps <chopps@labn.net>
6 # Copyright (c) 2021, LabN Consulting, L.L.C.
7 # Copyright (c) 2019-2020 by
8 # Donatas Abraitis <donatas.abraitis@gmail.com>
12 Test the timing of config operations.
14 The initial add of 10k routes is used as a baseline for timing and all future
15 operations are expected to complete in under 2 times that baseline. This is a
16 lot of slop; however, the pre-batching code some of these operations (e.g.,
17 adding the same set of 10k routes) would take 100 times longer, so the intention
18 is to catch those types of regressions.
27 from lib
import topotest
29 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
30 sys
.path
.append(os
.path
.join(CWD
, "../"))
32 # pylint: disable=C0413
33 from lib
.topogen
import Topogen
, TopoRouter
, get_topogen
34 from lib
.topolog
import logger
36 pytestmark
= [pytest
.mark
.staticd
]
41 switch
= tgen
.add_switch("s1")
42 switch
.add_link(tgen
.gears
["r1"])
45 def setup_module(mod
):
46 tgen
= Topogen(build_topo
, mod
.__name
__)
49 router_list
= tgen
.routers()
50 for rname
, router
in router_list
.items():
53 os
.path
.join(CWD
, "{}/zebra.conf".format(rname
)),
56 TopoRouter
.RD_STATIC
, os
.path
.join(CWD
, "{}/staticd.conf".format(rname
))
62 def teardown_module(mod
):
67 def get_ip_networks(super_prefix
, base_count
, count
):
68 count_log2
= math
.log(base_count
, 2)
69 if count_log2
!= int(count_log2
):
70 count_log2
= int(count_log2
) + 1
72 count_log2
= int(count_log2
)
73 network
= ipaddress
.ip_network(super_prefix
)
74 return tuple(network
.subnets(count_log2
))[0:count
]
77 def test_static_timing():
80 if tgen
.routers_have_failure():
81 pytest
.skip(tgen
.errors
)
94 router_list
= tgen
.routers()
97 optype
= "adding" if add
else "removing"
98 iptype
= "IPv6" if do_ipv6
else "IPv4"
99 if super_prefix
is None:
100 super_prefix
= u
"2001::/48" if do_ipv6
else u
"10.0.0.0/8"
102 optyped
= "added" if add
else "removed"
104 for rname
, router
in router_list
.items():
105 router
.logger
.info("{} {} static {} routes".format(optype
, count
, iptype
))
107 # Generate config file.
108 config_file
= os
.path
.join(
109 router
.logdir
, rname
, "{}-routes-{}.conf".format(iptype
.lower(), optype
)
111 with
open(config_file
, "w") as f
:
112 for i
, net
in enumerate(
113 get_ip_networks(super_prefix
, base_count
, count
)
117 f
.write("ip route {} {} bad_input\n".format(net
, via
))
119 f
.write("no ip route {} {} bad_input\n".format(net
, via
))
121 f
.write("ip route {} {}\n".format(net
, via
))
123 f
.write("no ip route {} {}\n".format(net
, via
))
127 router
.vtysh_cmd("debug northbound callbacks configuration")
130 load_command
= 'vtysh -f "{}"'.format(config_file
)
131 tstamp
= datetime
.datetime
.now()
132 output
= router
.run(load_command
)
133 delta
= (datetime
.datetime
.now() - tstamp
).total_seconds()
137 "\nvtysh command => {}\nvtysh output <= {}\nin {}s".format(
138 load_command
, output
, delta
142 limit_delta
= base_delta
* d_multiplier
144 "{} {} {} static routes under {} in {}s (limit: {}s)".format(
145 optyped
, count
, iptype
.lower(), super_prefix
, tot_delta
, limit_delta
149 assert tot_delta
<= limit_delta
153 # Number of static routes
154 router
= tgen
.gears
["r1"]
155 output
= router
.net
.cmd_legacy("vtysh -h | grep address-sanitizer", warn
=False)
157 logger
.info("No Address Sanitizer, generating 10000 routes")
160 logger
.info("Address Sanitizer build, only testing 50 routes")
164 [u
"10.0.0.0/8", u
"11.0.0.0/8"],
165 [u
"2100:1111:2220::/44", u
"2100:3333:4440::/44"],
168 # This apparently needed to allow for various mgmtd/staticd/zebra connections to form
169 # which then SLOWS execution down. If we don't include this value then the
170 # initial, baseline establishing, time is 2 time faster (e.g., 5s instead of 10s),
171 # but all later runs are slower and fail.
173 # This should be done differently based on actual facts.
177 for ipv6
in [False, True]:
178 base_delta
= do_config(
186 prefix_base
[ipv6
][0],
189 # Another set of same number of prefixes
198 prefix_base
[ipv6
][1],
210 prefix_base
[ipv6
][0],
213 # Remove 1/2 of duplicate
222 prefix_base
[ipv6
][0],
225 # Add all back in so 1/2 replicate 1/2 new
234 prefix_base
[ipv6
][0],
246 prefix_base
[ipv6
][0],
256 prefix_base
[ipv6
][1],
260 if __name__
== "__main__":
261 args
= ["-s"] + sys
.argv
[1:]
262 sys
.exit(pytest
.main(args
))