Esempio n. 1
0
    def process_request(self):
        req = self._prefix_mgr_server_socket.recv_thrift_obj(
            prefix_mgr_types.PrefixManagerRequest)

        if req.cmd == prefix_mgr_types.PrefixManagerCommand.ADD_PREFIXES:
            for prefix_entry in req.prefixes:
                self._prefix_map[sprint_prefix(
                    prefix_entry.prefix)] = prefix_entry
            self._prefix_mgr_server_socket.send_thrift_obj(
                prefix_mgr_types.PrefixManagerResponse(success=True))

        if req.cmd == prefix_mgr_types.PrefixManagerCommand.WITHDRAW_PREFIXES:
            success = False
            for prefix_entry in req.prefixes:
                prefix_str = sprint_prefix(prefix_entry.prefix)
                if prefix_str in self._prefix_map:
                    del self._prefix_map[prefix_str]
                    success = True
            self._prefix_mgr_server_socket.send_thrift_obj(
                prefix_mgr_types.PrefixManagerResponse(success=success))

        if req.cmd == prefix_mgr_types.PrefixManagerCommand.GET_ALL_PREFIXES:
            resp = prefix_mgr_types.PrefixManagerResponse()
            resp.prefixes = self._prefix_map.values()
            resp.success = True
            self._prefix_mgr_server_socket.send_thrift_obj(resp)
Esempio n. 2
0
        def _parse(loopback_set, prefix_db):
            for prefix_entry in prefix_db.prefixEntries:
                # Only consider v6 address
                if len(prefix_entry.prefix.prefixAddress.addr) != 16:
                    continue

                # Parse PrefixAllocator address
                if prefix_entry.type == lsdb_types.PrefixType.PREFIX_ALLOCATOR:
                    prefix = utils.sprint_prefix(prefix_entry.prefix)
                    if prefix_entry.prefix.prefixLength == 128:
                        prefix = prefix.split('/')[0]
                    else:
                        # TODO: we should ideally get address with last bit
                        # set to 1. `python3.6 ipaddress` libraries does this
                        # in one line. Alas no easy options with ipaddr
                        # NOTE: In our current usecase we are just assuming
                        # that allocated prefix has last 16 bits set to 0
                        prefix = prefix.split('/')[0] + '1'
                    loopback_set.add(prefix)
                    continue

                # Parse LOOPBACK address
                if prefix_entry.type == lsdb_types.PrefixType.LOOPBACK:
                    prefix = utils.sprint_prefix(prefix_entry.prefix)
                    loopback_set.add(prefix.split('/')[0])
                    continue
Esempio n. 3
0
 def __init__(self, zmq_ctx, url):
     self._prefix_mgr_server_socket = socket.Socket(zmq_ctx, zmq.REP)
     self._prefix_mgr_server_socket.bind(url)
     self._prefix_map = {
         sprint_prefix(prefix_entry1.prefix): prefix_entry1,
         sprint_prefix(prefix_entry2.prefix): prefix_entry2,
         sprint_prefix(prefix_entry3.prefix): prefix_entry3
     }
Esempio n. 4
0
    def get_nexthop_nodes(self, route_db, dst_addr, cur_lpm_len,
                          if2node, fib_routes, in_fib):
        ''' get the next hop nodes.
        if the longest prefix is coming from the current node,
        return an empty list to terminate the path searching. '''

        next_hop_nodes = []
        is_initialized = fib_routes[route_db.thisNodeName]

        lpm_route = self.get_lpm_route(route_db, dst_addr)
        if lpm_route and lpm_route.prefix.prefixLength >= cur_lpm_len:
            if in_fib and not is_initialized:
                fib_routes[route_db.thisNodeName].extend(
                    self.get_fib_path(
                        route_db.thisNodeName,
                        utils.sprint_prefix(lpm_route.prefix),
                        self.fib_agent_port,
                        self.timeout))
            min_cost = min([p.metric for p in lpm_route.paths])
            for path in [p for p in lpm_route.paths if p.metric == min_cost]:
                if len(path.nextHop.addr) == 16:
                    nh_addr = utils.sprint_addr(path.nextHop.addr)
                    next_hop_node_name = \
                        if2node[route_db.thisNodeName][(path.ifName, nh_addr)]
                    next_hop_nodes.append([
                        next_hop_node_name,
                        path.ifName,
                        path.metric,
                        nh_addr,
                    ])
        return next_hop_nodes
Esempio n. 5
0
    def get_nexthop_nodes(self, route_db, dst_addr, cur_lpm_len, if2node,
                          fib_routes, in_fib):
        ''' get the next hop nodes.
        if the longest prefix is coming from the current node,
        return an empty list to terminate the path searching. '''

        next_hop_nodes = []
        is_initialized = fib_routes[route_db.thisNodeName]

        for lpm_route in self.get_lpm_routes(route_db, dst_addr):
            if lpm_route.prefix.prefixLength <= cur_lpm_len:
                continue
            if in_fib and not is_initialized:
                fib_routes[route_db.thisNodeName].extend(
                    self.get_fib_path(route_db.thisNodeName,
                                      utils.sprint_prefix(lpm_route.prefix),
                                      self.fib_agent_port, self.timeout))

            for path in lpm_route.paths:
                if len(path.nextHop.addr) == 16:
                    next_hop_node_name = if2node[route_db.thisNodeName][
                        path.ifName]
                    next_hop_nodes.append([
                        next_hop_node_name, path.ifName, path.metric,
                        utils.sprint_addr(path.nextHop.addr)
                    ])

        return next_hop_nodes
Esempio n. 6
0
    def get_lpm_route(self, route_db, dst_addr):
        ''' find the routes to the longest prefix matches of dst. '''

        max_prefix_len = -1
        lpm_route = None
        for route in route_db.routes:
            if IPNetwork(utils.sprint_prefix(route.prefix)).Contains(
                    IPAddress(dst_addr)):
                next_hop_prefix_len = route.prefix.prefixLength
                if next_hop_prefix_len == max_prefix_len:
                    raise Exception('Duplicate prefix found in routing table {}'
                                    .format(utils.sprint_prefix(route.prefix)))
                elif next_hop_prefix_len > max_prefix_len:
                    lpm_route = route
                    max_prefix_len = next_hop_prefix_len

        return lpm_route
Esempio n. 7
0
 def run(self):
     resp = self.client.view_prefix()
     rows = []
     for prefix_entry in resp.prefixes:
         prefix_str = utils.sprint_prefix(prefix_entry.prefix)
         prefix_type = utils.sprint_prefix_type(prefix_entry.type)
         rows.append((prefix_type, prefix_str))
     print('\n', printing.render_horizontal_table(rows, ['Type', 'Prefix']))
     print()
Esempio n. 8
0
 def _parse_nodes(rows, value):
     prefix_db = deserialize_thrift_object(value.value,
                                           lsdb_types.PrefixDatabase)
     marker = '* ' if prefix_db.thisNodeName == host_id else '> '
     row = ["{}{}".format(marker, prefix_db.thisNodeName)]
     loopback_prefixes = [p.prefix for p in prefix_db.prefixEntries \
              if p.type == lsdb_types.PrefixType.LOOPBACK]
     row.extend([utils.sprint_prefix(p) for p in loopback_prefixes])
     rows.append(row)
Esempio n. 9
0
def print_routes(caption, routes):

    route_strs = []
    for route in routes:
        dest = utils.sprint_prefix(route.dest)
        paths_str = '\n'.join(
            ["via {}".format(ip_nexthop_to_str(nh)) for nh in route.nexthops])
        route_strs.append((dest, paths_str))

    print(printing.render_vertical_table(route_strs, caption=caption))
Esempio n. 10
0
 def _parse_nodes(rows, value):
     prefix_db = serializer.deserialize_thrift_object(
         value.value, lsdb_types.PrefixDatabase)
     marker = '* ' if prefix_db.thisNodeName == host_id else '> '
     row = ["{}{}".format(marker, prefix_db.thisNodeName)]
     loopback_prefixes = [
         p.prefix for p in prefix_db.prefixEntries
         if p.type == lsdb_types.PrefixType.LOOPBACK
     ]
     loopback_prefixes.sort(key=lambda x: len(x.prefixAddress.addr),
                            reverse=True)
     row.extend([utils.sprint_prefix(p) for p in loopback_prefixes])
     rows.append(row)
Esempio n. 11
0
    def get_fib_path(self, src, dst_prefix, fib_agent_port, timeout):
        src_addr = self.get_loopback_addr(src)
        if src_addr is None:
            return []

        try:
            client = utils.get_fib_agent_client(
                src_addr, fib_agent_port, timeout)
            routes = client.getRouteTableByClient(client.client_id)
        except Exception:
            return []
        for route in routes:
            if utils.sprint_prefix(route.dest) == dst_prefix:
                return route.nexthops
        return []
Esempio n. 12
0
    def get_fib_path(self, src, dst_prefix, fib_agent_port, timeout):
        try:
            client = utils.get_fib_agent_client(src, fib_agent_port, timeout)
            routes = client.getRouteTableByClient(client.client_id)
        except Exception:
            try:
                client = utils.get_fib_agent_client(src, fib_agent_port,
                                                    timeout)
                routes = client.getRouteTableByClient(client.client_id)
            except Exception:
                return []

        for route in routes:
            if utils.sprint_prefix(route.dest) == dst_prefix:
                return route.nexthops
        return []
Esempio n. 13
0
    def get_lpm_routes(self, route_db, dst_addr):
        ''' find the routes to the longest prefix matches of dst. '''

        max_prefix_len = 0
        lpm_routes = []
        for route in route_db.routes:
            if IPNetwork(utils.sprint_prefix(route.prefix)).Contains(
                    IPAddress(dst_addr)):
                next_hop_prefix_len = route.prefix.prefixLength
                if next_hop_prefix_len == max_prefix_len:
                    lpm_routes.append(route)
                elif next_hop_prefix_len > max_prefix_len:
                    lpm_routes = [route]
                    max_prefix_len = next_hop_prefix_len

        return lpm_routes
Esempio n. 14
0
def print_routes(caption, routes, prefixes=None):

    networks = None
    if prefixes:
        networks = [ipaddr.IPNetwork(p) for p in prefixes]

    route_strs = []
    for route in routes:
        dest = utils.sprint_prefix(route.dest)
        if not utils.contain_any_prefix(dest, networks):
            continue

        paths_str = '\n'.join(
            ["via {}".format(ip_nexthop_to_str(nh)) for nh in route.nexthops])
        route_strs.append((dest, paths_str))

    print(printing.render_vertical_table(route_strs, caption=caption))
Esempio n. 15
0
def get_route_as_dict(routes):
    '''
    Convert a routeDb into a dict representing routes in str format

    :param routes: list ip_types.UnicastRoute (structured routes)

    :returns: dict of routes (prefix : [nexthops]
    :rtype: dict
    '''

    # Thrift object instances do not have hash support
    # Make custom stringified object so we can hash and diff
    # dict of prefixes(str) : nexthops(str)
    routes_dict = {
        utils.sprint_prefix(route.dest):
        sorted([ip_nexthop_to_str(nh) for nh in route.nexthops])
        for route in routes
    }

    return routes_dict
Esempio n. 16
0
 def _parse(prefix_set, prefix_db):
     for prefix_entry in prefix_db.prefixEntries:
         if len(prefix_entry.prefix.prefixAddress.addr) == 16:
             prefix_set.add(utils.sprint_prefix(prefix_entry.prefix))
Esempio n. 17
0
 def _parse(loopback_set, prefix_db):
     for prefix_entry in prefix_db.prefixEntries:
         if (prefix_entry.type == lsdb_types.PrefixType.LOOPBACK
                 and len(prefix_entry.prefix.prefixAddress.addr) == 16):
             loopback_set.add(utils.sprint_prefix(prefix_entry.prefix))