Exemplo n.º 1
0
 def __init__(self, **kwargs):
     for kw, arg in StressRouteInsertion.defaults.items():
         setattr(self, kw, arg)
     for kw, arg in kwargs.items():
         setattr(self, kw, arg)
     self.routes = {}
     self.generation = 1
     if (self.host is None) or (self.port is None):
         raise Exception("Test needs to specify 'host' and 'port' options")
     if self.maxprefix > 120:
         raise Exception("Error: this tool is not yet smart" +
                         " enough to do maxprefix > 120")
     random.seed(self.randseed)
     self.client = PlainTextFbossAgentClient(host=self.host, port=self.port)
     # a list of next hops; all routes point to same one: DROP
     self.nexthops = [utils.ip_to_binary(nh) for nh in []]
     self.client_id = 31336  # ID for our routes
Exemplo n.º 2
0
class StressRouteInsertion(object):
    """ Measure latency of bulk route thrashing.

    Algorithm:
            1) Insert $entries randomly generated v6 route entries
            2) For loop = 1 to $loops:
                a) remove $percent percent of the routes, randomly
                b) generate a new set of $percent routes
                b) start the clock
                c) add new routes
                d) stop the clock and record the time

    The theory is this roughly emulates worst case of BGP sessions
    coming and going over time.  The $percent variable should
    correspond to a worst case guess as to the number of routes
    in a peering session.
    """

    defaults = {
        "host": "localhost",
        "port": 5909,
        "entries": 4000,
        "percent": 10,
        "loops": 5,
        "minprefix": 16,
        "maxprefix": 64,
        "pause_on_exit": False,
        "randseed": 0,  # we're going for pseudorandom, not real random
    }

    def __init__(self, **kwargs):
        for kw, arg in StressRouteInsertion.defaults.items():
            setattr(self, kw, arg)
        for kw, arg in kwargs.items():
            setattr(self, kw, arg)
        self.routes = {}
        self.generation = 1
        if (self.host is None) or (self.port is None):
            raise Exception("Test needs to specify 'host' and 'port' options")
        if self.maxprefix > 120:
            raise Exception("Error: this tool is not yet smart" +
                            " enough to do maxprefix > 120")
        random.seed(self.randseed)
        self.client = PlainTextFbossAgentClient(host=self.host, port=self.port)
        # a list of next hops; all routes point to same one: DROP
        self.nexthops = [utils.ip_to_binary(nh) for nh in []]
        self.client_id = 31336  # ID for our routes

    def generate_random_routes(self, n=None):
        # store routes as a dict to prevent duplications
        if n is None:
            n = self.entries
        routes = {}
        while len(routes) < n:
            routes[self.gen_rand_route()] = self.generation
        return routes

    def gen_rand_route(self):
        """ Generate a random IPv6 route as a string

        @NOTE: doesn't work for prefix > 120 bits"""
        prefix = random.randint(self.minprefix, self.maxprefix)  # inclusive
        r = ""
        for i in range(0, int(prefix / 4)):
            r += "{0:x}".format(random.randint(0, 15))
            if ((i + 1) % 4) == 0:
                r += ":"
        leftover = prefix - (i * 4)
        # this ensures we don't end with a ':' as well
        r += "{0:x}".format(random.randint(0, 15) & (pow(2, leftover) - 1))
        return r + "::1/{}".format(prefix)

    def insert_routes(self, routes):
        uniRoutes = []
        for route in routes:
            ip, prefix = route.split("/")
            addr = utils.ip_to_binary(ip)
            ipRoute = IpPrefix(ip=addr, prefixLength=prefix)
            uniRoutes.append(
                UnicastRoute(dest=ipRoute, nextHopAddrs=self.nexthops))
        self.client.addUnicastRoutes(self.client_id, uniRoutes)

    def delete_routes(self, routes):
        uniRoutes = []
        for route in routes:
            ip, prefix = route.split("/")
            addr = utils.ip_to_binary(ip)
            uniRoutes.append(IpPrefix(ip=addr, prefixLength=prefix))
        self.client.deleteUnicastRoutes(self.client_id, uniRoutes)

    def clean_up(self):
        print("Removing all routes")
        self.delete_routes(self.routes)
        self.client._socket.close()
        print("...done.")

    def run_test(self):
        """ Run actual test """
        print(
            "Generating {} random routes with prefix between {} and {}".format(
                self.entries, self.minprefix, self.maxprefix))
        self.routes = self.generate_random_routes()
        print("... done.")

        print("Inserting initial routes into the switch...")
        start = time.clock()
        self.insert_routes(self.routes)
        stop = time.clock()
        print(" ... done : {} seconds - not the real test, but FYI".format(
            stop - start))

        target = (1 - (self.percent / 100)) * self.entries
        for loop in range(0, self.loops):
            print("--- Starting loop {}...".format(loop))
            print("Deleting {} routes".format(self.entries - target))
            delete_routes = []
            while len(self.routes) > target:
                route = random.choice(list(self.routes.keys()))
                delete_routes.append(route)
                del self.routes[route]
            self.delete_routes(delete_routes)
            print("Picking {} new routes".format(self.entries - target))
            new_routes = self.generate_random_routes(n=self.entries - target)
            print("Adding new routes")
            start = time.clock()
            for route in new_routes:
                self.routes[route] = loop
            self.insert_routes(new_routes)
            stop = time.clock()
            print("RESULT: {} seconds to add {} new routes".format(
                stop - start, self.entries - target))
        if self.pause_on_exit:
            input("\n\n\nTest Done -- press return to cleanup: ")