From bbbd12f197c546215512ab0cf649972a74b0b6aa Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 10 Jun 2020 23:12:34 -0400 Subject: [PATCH] tests: Add some scale tests to ensure things work Add some basic route scale tests to ensure that we can install a large number of routes. Also grab some timings so that we can keep track and see if anything substantially changes over time. Signed-off-by: Donald Sharp --- .../route-scale/r1/installed.routes.json | 16 ++ tests/topotests/route-scale/r1/no.routes.json | 11 + tests/topotests/route-scale/r1/sharpd.conf | 76 +++++++ tests/topotests/route-scale/r1/zebra.conf | 96 ++++++++ .../topotests/route-scale/test_route_scale.py | 211 ++++++++++++++++++ 5 files changed, 410 insertions(+) create mode 100644 tests/topotests/route-scale/r1/installed.routes.json create mode 100644 tests/topotests/route-scale/r1/no.routes.json create mode 100644 tests/topotests/route-scale/r1/sharpd.conf create mode 100644 tests/topotests/route-scale/r1/zebra.conf create mode 100755 tests/topotests/route-scale/test_route_scale.py diff --git a/tests/topotests/route-scale/r1/installed.routes.json b/tests/topotests/route-scale/r1/installed.routes.json new file mode 100644 index 0000000000..25d209f9eb --- /dev/null +++ b/tests/topotests/route-scale/r1/installed.routes.json @@ -0,0 +1,16 @@ +{ + "routes":[ + { + "fib":32, + "rib":32, + "type":"connected" + }, + { + "fib":1000000, + "rib":1000000, + "type":"sharp" + } + ], + "routesTotal":1000032, + "routesTotalFib":1000032 +} diff --git a/tests/topotests/route-scale/r1/no.routes.json b/tests/topotests/route-scale/r1/no.routes.json new file mode 100644 index 0000000000..abebd1b143 --- /dev/null +++ b/tests/topotests/route-scale/r1/no.routes.json @@ -0,0 +1,11 @@ +{ + "routes":[ + { + "fib":32, + "rib":32, + "type":"connected" + } + ], + "routesTotal":32, + "routesTotalFib":32 +} diff --git a/tests/topotests/route-scale/r1/sharpd.conf b/tests/topotests/route-scale/r1/sharpd.conf new file mode 100644 index 0000000000..0848f34ddf --- /dev/null +++ b/tests/topotests/route-scale/r1/sharpd.conf @@ -0,0 +1,76 @@ +! +nexthop-group one + nexthop 192.168.0.1 r1-eth0 +! +nexthop-group two + nexthop 192.168.0.1 r1-eth0 + nexthop 192.168.1.1 r1-eth1 +! +nexthop-group four + nexthop 192.168.0.1 r1-eth0 + nexthop 192.168.1.1 r1-eth1 + nexthop 192.168.2.1 r1-eth2 + nexthop 192.168.3.1 r1-eth3 +! +nexthop-group eight + nexthop 192.168.0.1 r1-eth0 + nexthop 192.168.1.1 r1-eth1 + nexthop 192.168.2.1 r1-eth2 + nexthop 192.168.3.1 r1-eth3 + nexthop 192.168.4.1 r1-eth4 + nexthop 192.168.5.1 r1-eth5 + nexthop 192.168.6.1 r1-eth6 + nexthop 192.168.7.1 r1-eth7 +! +nexthop-group sixteen + nexthop 192.168.0.1 r1-eth0 + nexthop 192.168.1.1 r1-eth1 + nexthop 192.168.2.1 r1-eth2 + nexthop 192.168.3.1 r1-eth3 + nexthop 192.168.4.1 r1-eth4 + nexthop 192.168.5.1 r1-eth5 + nexthop 192.168.6.1 r1-eth6 + nexthop 192.168.7.1 r1-eth7 + nexthop 192.168.8.1 r1-eth8 + nexthop 192.168.9.1 r1-eth9 + nexthop 192.168.10.1 r1-eth10 + nexthop 192.168.11.1 r1-eth11 + nexthop 192.168.12.1 r1-eth12 + nexthop 192.168.13.1 r1-eth13 + nexthop 192.168.14.1 r1-eth14 + nexthop 192.168.15.1 r1-eth15 +! +nexthop-group thirtytwo + nexthop 192.168.0.1 r1-eth0 + nexthop 192.168.1.1 r1-eth1 + nexthop 192.168.2.1 r1-eth2 + nexthop 192.168.3.1 r1-eth3 + nexthop 192.168.4.1 r1-eth4 + nexthop 192.168.5.1 r1-eth5 + nexthop 192.168.6.1 r1-eth6 + nexthop 192.168.7.1 r1-eth7 + nexthop 192.168.8.1 r1-eth8 + nexthop 192.168.9.1 r1-eth9 + nexthop 192.168.10.1 r1-eth10 + nexthop 192.168.11.1 r1-eth11 + nexthop 192.168.12.1 r1-eth12 + nexthop 192.168.13.1 r1-eth13 + nexthop 192.168.14.1 r1-eth14 + nexthop 192.168.15.1 r1-eth15 + nexthop 192.168.16.1 r1-eth16 + nexthop 192.168.17.1 r1-eth17 + nexthop 192.168.18.1 r1-eth18 + nexthop 192.168.19.1 r1-eth19 + nexthop 192.168.20.1 r1-eth20 + nexthop 192.168.21.1 r1-eth21 + nexthop 192.168.22.1 r1-eth22 + nexthop 192.168.23.1 r1-eth23 + nexthop 192.168.24.1 r1-eth24 + nexthop 192.168.25.1 r1-eth25 + nexthop 192.168.26.1 r1-eth26 + nexthop 192.168.27.1 r1-eth27 + nexthop 192.168.28.1 r1-eth28 + nexthop 192.168.29.1 r1-eth29 + nexthop 192.168.30.1 r1-eth30 + nexthop 192.168.31.1 r1-eth31 +! \ No newline at end of file diff --git a/tests/topotests/route-scale/r1/zebra.conf b/tests/topotests/route-scale/r1/zebra.conf new file mode 100644 index 0000000000..48a01f48ab --- /dev/null +++ b/tests/topotests/route-scale/r1/zebra.conf @@ -0,0 +1,96 @@ +int r1-eth0 + ip addr 192.168.0.1/24 +! +int r1-eth1 + ip addr 192.168.1.1/24 +! +int r1-eth2 + ip addr 192.168.2.1/24 +! +int r1-eth3 + ip addr 192.168.3.1/24 +! +int r1-eth4 + ip addr 192.168.4.1/24 +! +int r1-eth5 + ip addr 192.168.5.1/24 +! +int r1-eth6 + ip addr 192.168.6.1/24 +! +int r1-eth7 + ip addr 192.168.7.1/24 +! +int r1-eth8 + ip addr 192.168.8.1/24 +! +int r1-eth9 + ip addr 192.168.9.1/24 +! +int r1-eth10 + ip addr 192.168.10.1/24 +! +int r1-eth11 + ip addr 192.168.11.1/24 +! +int r1-eth12 + ip addr 192.168.12.1/24 +! +int r1-eth13 + ip addr 192.168.13.1/24 +! +int r1-eth14 + ip addr 192.168.14.1/24 +! +int r1-eth15 + ip addr 192.168.15.1/24 +! +int r1-eth16 + ip addr 192.168.16.1/24 +! +int r1-eth17 + ip addr 192.168.17.1/24 +! +int r1-eth18 + ip addr 192.168.18.1/24 +! +int r1-eth19 + ip addr 192.168.19.1/24 +! +int r1-eth20 + ip addr 192.168.20.1/24 +! +int r1-eth21 + ip addr 192.168.21.1/24 +! +int r1-eth22 + ip addr 192.168.22.1/24 +! +int r1-eth23 + ip addr 192.168.23.1/24 +! +int r1-eth24 + ip addr 192.168.24.1/24 +! +int r1-eth25 + ip addr 192.168.25.1/24 +! +int r1-eth26 + ip addr 192.168.26.1/24 +! +int r1-eth27 + ip addr 192.168.27.1/24 +! +int r1-eth28 + ip addr 192.168.28.1/24 +! +int r1-eth29 + ip addr 192.168.29.1/24 +! +int r1-eth30 + ip addr 192.168.30.1/24 +! +int r1-eth31 + ip addr 192.168.31.1/24 +! \ No newline at end of file diff --git a/tests/topotests/route-scale/test_route_scale.py b/tests/topotests/route-scale/test_route_scale.py new file mode 100755 index 0000000000..9ba0c7e50e --- /dev/null +++ b/tests/topotests/route-scale/test_route_scale.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python + +# +# test_route_scale.py +# +# Copyright (c) 2020 by +# Cumulus Networks, Inc. +# Donald Sharp +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +test_route_scale.py: Testing route scale + +""" + +import os +import re +import sys +import pytest +import json +from functools import partial + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger +from lib.common_config import shutdown_bringup_interface + +# Required to instantiate the topology builder class. +from mininet.topo import Topo + +##################################################### +## +## Network Topology Definition +## +##################################################### + + +class NetworkTopo(Topo): + "Route Scale Topology" + + def build(self, **_opts): + "Build function" + + tgen = get_topogen(self) + + # Populate routers + for routern in range(1, 2): + tgen.add_router("r{}".format(routern)) + + # Populate switches + for switchn in range(1, 33): + switch = tgen.add_switch("sw{}".format(switchn)) + switch.add_link(tgen.gears["r1"]) + + +##################################################### +## +## Tests starting +## +##################################################### + + +def setup_module(module): + "Setup topology" + tgen = Topogen(NetworkTopo, module.__name__) + tgen.start_topology() + + router_list = tgen.routers() + for rname, router in router_list.iteritems(): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format(rname)) + ) + + tgen.start_router() + #tgen.mininet_cli() + +def teardown_module(_mod): + "Teardown the pytest environment" + tgen = get_topogen() + + # This function tears down the whole topology. + tgen.stop_topology() + +def test_converge_protocols(): + "Wait for protocol convergence" + + tgen = get_topogen() + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + +def test_route_install(): + "Test route install for a variety of ecmp" + + tgen = get_topogen() + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + installed_file = "{}/r1/installed.routes.json".format(CWD) + expected_installed = json.loads(open(installed_file).read()) + + removed_file = "{}/r1/no.routes.json".format(CWD) + expected_removed = json.loads(open(removed_file).read()) + + r1 = tgen.gears["r1"] + + r1.vtysh_cmd("sharp install route 1.0.0.0 nexthop-group one 1000000", isjson=False) + test_func = partial(topotest.router_json_cmp, r1, "show ip route summary json", expected_installed) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=5) + output = r1.vtysh_cmd("sharp data route", isjson=False) + logger.info("1 million routes X 1 ecmp installed") + logger.info(output) + r1.vtysh_cmd("sharp remove route 1.0.0.0 1000000", isjson=False) + test_func = partial(topotest.router_json_cmp, r1, "show ip route summary json", expected_removed) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=5) + output = r1.vtysh_cmd("sharp data route", isjson=False) + logger.info("1 million routes x 1 ecmp removed") + logger.info(output) + + r1.vtysh_cmd("sharp install route 1.0.0.0 nexthop-group two 1000000", isjson=False) + test_func = partial(topotest.router_json_cmp, r1, "show ip route summary json", expected_installed) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=5) + output = r1.vtysh_cmd("sharp data route", isjson=False) + logger.info("1 million routes X 2 ecmp installed") + logger.info(output) + r1.vtysh_cmd("sharp remove route 1.0.0.0 1000000", isjson=False) + test_func = partial(topotest.router_json_cmp, r1, "show ip route summary json", expected_removed) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=5) + output = r1.vtysh_cmd("sharp data route", isjson=False) + logger.info("1 million routes x 2 ecmp removed") + logger.info(output) + + r1.vtysh_cmd("sharp install route 1.0.0.0 nexthop-group four 1000000", isjson=False) + test_func = partial(topotest.router_json_cmp, r1, "show ip route summary json", expected_installed) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=5) + output = r1.vtysh_cmd("sharp data route", isjson=False) + logger.info("1 million routes X 4 ecmp installed") + logger.info(output) + r1.vtysh_cmd("sharp remove route 1.0.0.0 1000000", isjson=False) + test_func = partial(topotest.router_json_cmp, r1, "show ip route summary json", expected_removed) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=5) + output = r1.vtysh_cmd("sharp data route", isjson=False) + logger.info("1 million routes x 4 ecmp removed") + logger.info(output) + + r1.vtysh_cmd("sharp install route 1.0.0.0 nexthop-group eight 1000000", isjson=False) + test_func = partial(topotest.router_json_cmp, r1, "show ip route summary json", expected_installed) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=5) + output = r1.vtysh_cmd("sharp data route", isjson=False) + logger.info("1 million routes X 8 ecmp installed") + logger.info(output) + r1.vtysh_cmd("sharp remove route 1.0.0.0 1000000", isjson=False) + test_func = partial(topotest.router_json_cmp, r1, "show ip route summary json", expected_removed) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=5) + output = r1.vtysh_cmd("sharp data route", isjson=False) + logger.info("1 million routes x 8 ecmp removed") + logger.info(output) + + r1.vtysh_cmd("sharp install route 1.0.0.0 nexthop-group sixteen 1000000", isjson=False) + test_func = partial(topotest.router_json_cmp, r1, "show ip route summary json", expected_installed) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=5) + output = r1.vtysh_cmd("sharp data route", isjson=False) + logger.info("1 million routes X 16 ecmp installed") + logger.info(output) + r1.vtysh_cmd("sharp remove route 1.0.0.0 1000000", isjson=False) + test_func = partial(topotest.router_json_cmp, r1, "show ip route summary json", expected_removed) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=5) + output = r1.vtysh_cmd("sharp data route", isjson=False) + logger.info("1 million routes x 16 ecmp removed") + logger.info(output) + + r1.vtysh_cmd("sharp install route 1.0.0.0 nexthop-group thirtytwo 1000000", isjson=False) + test_func = partial(topotest.router_json_cmp, r1, "show ip route summary json", expected_installed) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=5) + output = r1.vtysh_cmd("sharp data route", isjson=False) + logger.info("1 million routes X 32 ecmp installed") + logger.info(output) + r1.vtysh_cmd("sharp remove route 1.0.0.0 1000000", isjson=False) + test_func = partial(topotest.router_json_cmp, r1, "show ip route summary json", expected_removed) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=5) + output = r1.vtysh_cmd("sharp data route", isjson=False) + logger.info("1 million routes x 32 ecmp removed") + logger.info(output) + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args))