Beispiel #1
0
 def _run(self, client: OpenrCtrl.Client, nodes: set, bidir: bool,
          json: bool) -> None:
     adj_dbs = client.getDecisionAdjacencyDbs()
     adjs_map = utils.adj_dbs_to_dict(adj_dbs, nodes, bidir, self.iter_dbs)
     if json:
         utils.print_json(adjs_map)
     else:
         utils.print_adjs_table(adjs_map, self.enable_color, None, None)
Beispiel #2
0
    def get_dbs(self, client: OpenrCtrl.Client) -> Tuple[Dict, Dict, Dict]:
        # get LSDB from Decision
        decision_adj_dbs = client.getDecisionAdjacencyDbs()
        decision_prefix_dbs = client.getDecisionPrefixDbs()

        # get LSDB from KvStore
        kvstore_keyvals = client.getKvStoreKeyValsFiltered(
            kv_store_types.KeyDumpParams(Consts.ALL_DB_MARKER)).keyVals

        return (decision_adj_dbs, decision_prefix_dbs, kvstore_keyvals)
Beispiel #3
0
 def _run(self, client: OpenrCtrl.Client, nodes: set, bidir: bool,
          json: bool) -> None:
     adj_dbs = client.getDecisionAdjacencyDbs()
     adjs_map = utils.adj_dbs_to_dict(adj_dbs, nodes, bidir, self.iter_dbs)
     for _, val in adjs_map.items():
         for adj_entry in val["adjacencies"]:
             adj_entry["area"] = val.get("area", "N/A")
     if json:
         utils.print_json(adjs_map)
     else:
         utils.print_adjs_table(adjs_map, None, None)
Beispiel #4
0
    def get_dbs(self, client: OpenrCtrl.Client, area: str) -> Tuple[Dict, Dict, Dict]:
        # get LSDB from Decision
        decision_adj_dbs = client.getDecisionAdjacencyDbs()
        decision_prefix_dbs = client.getDecisionPrefixDbs()

        area = utils.get_area_id(client, area)
        # get LSDB from KvStore
        params = openr_types.KeyDumpParams(Consts.ALL_DB_MARKER)
        params.keys = [Consts.ALL_DB_MARKER]
        if area is None:
            kvstore_keyvals = client.getKvStoreKeyValsFiltered(params).keyVals
        else:
            kvstore_keyvals = client.getKvStoreKeyValsFilteredArea(params, area).keyVals

        return (decision_adj_dbs, decision_prefix_dbs, kvstore_keyvals)
Beispiel #5
0
    def get_paths(self, client: OpenrCtrl.Client, src: str, dst: str,
                  max_hop: int) -> Any:
        """
        calc paths from src to dst using backtracking. can add memoization to
        convert to dynamic programming for better scalability when network is large.
        """

        dst_addr = dst
        # if dst is node, we get its loopback addr
        if ":" not in dst:
            dst_addr = self.get_loopback_addr(dst)
        try:
            ipaddress.ip_address(dst_addr)
        except ValueError:
            try:
                dst_addr = str(
                    ipaddress.ip_network(dst, strict=False).network_address)
            except ValueError:
                print("node name or ip address not valid.")
                sys.exit(1)

        adj_dbs = client.getDecisionAdjacencyDbs()
        if2node = self.get_if2node_map(adj_dbs)
        fib_routes = defaultdict(list)

        paths = []

        def _backtracking(cur, path, hop, visited, in_fib):
            """
            Depth-first search (DFS) for traversing graph and getting paths
            from src to dst with lowest metric in total.

            Attributes:
                cur: current starting node
                path: a list of the nodes who form the path from src to the current node
                hop: how many hops from src node to the current node
                visited: a set of visited nodes
                in_fib: if current node is in fib path
            """
            if hop > max_hop:
                return

            # get the longest prefix match for dst_addr from current node's advertising prefixes
            cur_lpm_len = self.get_lpm_len_from_node(cur, dst_addr)
            # get the next hop nodes
            next_hop_nodes = self.get_nexthop_nodes(
                client.getRouteDbComputed(cur),
                dst_addr,
                cur_lpm_len,
                if2node,
                fib_routes,
                in_fib,
            )

            if len(next_hop_nodes) == 0:
                if hop != 1:
                    paths.append((in_fib, path[:]))
                return

            for next_hop_node in next_hop_nodes:
                next_hop_node_name = next_hop_node[0]
                # prevent loops
                if next_hop_node_name in visited:
                    return

                path.append([hop] + next_hop_node)
                visited.add(next_hop_node_name)

                # check if next hop node is in fib path
                is_nexthop_in_fib_path = False
                for nexthop in fib_routes[cur]:
                    if (next_hop_node[3] == ipnetwork.sprint_addr(nexthop.addr)
                            and next_hop_node[1] == nexthop.ifName):
                        is_nexthop_in_fib_path = True

                # recursion - extend the path from next hop node
                _backtracking(
                    next_hop_node_name,
                    path,
                    hop + 1,
                    visited,
                    is_nexthop_in_fib_path and in_fib,
                )
                visited.remove(next_hop_node_name)
                path.pop()

        # initial call to begin the DFS to search paths
        visited_set = set()
        visited_set.add(src)
        _backtracking(src, [], 1, visited_set, True)
        return paths
Beispiel #6
0
    def get_paths(self, client: OpenrCtrl.Client, src: str, dst: str,
                  max_hop: int) -> Any:
        """
        calc paths from src to dst using backtracking. can add memoization to
        convert to dynamic programming for better scalability when network is large.
        """

        dst_addr = dst
        # if dst is node, we get its loopback addr
        if ":" not in dst:
            dst_addr = self.get_loopback_addr(dst)
        try:
            ipaddress.ip_address(dst_addr)
        except ValueError:
            try:
                dst_addr = str(
                    ipaddress.ip_network(dst, strict=False).network_address)
            except ValueError:
                print("node name or ip address not valid.")
                sys.exit(1)

        adj_dbs = client.getDecisionAdjacencyDbs()
        if2node = self.get_if2node_map(adj_dbs)
        fib_routes = defaultdict(list)

        paths = []

        def _backtracking(cur, path, hop, visited, in_fib):
            if hop > max_hop:
                return

            cur_lpm_len = self.get_lpm_len_from_node(cur, dst_addr)
            next_hop_nodes = self.get_nexthop_nodes(
                client.getRouteDbComputed(cur),
                dst_addr,
                cur_lpm_len,
                if2node,
                fib_routes,
                in_fib,
            )

            if len(next_hop_nodes) == 0:
                if hop != 1:
                    paths.append((in_fib, path[:]))
                return

            for next_hop_node in next_hop_nodes:
                next_hop_node_name = next_hop_node[0]
                # prevent loops
                if next_hop_node_name in visited:
                    return

                path.append([hop] + next_hop_node)
                visited.add(next_hop_node_name)

                # check if next hop node is in fib path
                is_nexthop_in_fib_path = False
                for nexthop in fib_routes[cur]:
                    if (next_hop_node[3] == ipnetwork.sprint_addr(nexthop.addr)
                            and next_hop_node[1] == nexthop.ifName):
                        is_nexthop_in_fib_path = True

                _backtracking(
                    next_hop_node_name,
                    path,
                    hop + 1,
                    visited,
                    is_nexthop_in_fib_path and in_fib,
                )
                visited.remove(next_hop_node_name)
                path.pop()

        _backtracking(src, [], 1, set(src), True)
        return paths