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)
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)
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)
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)
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
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