Example #1
0
 def _get_proxy_routes(self, points):
     for prefix, parts in groupby(sorted(points, key=itemgetter(3)),
                                  key=itemgetter(3)):
         route = []
         for p in parts:
             src, dst, cost = p[0], p[1], p[2]
             if cost >= 0:
                 src = None
             fwd_addr = self.root.get_fwd_address(src, dst)
             # Can have multiple private addresses per interface, handle
             # here the selection ...
             if isinstance(fwd_addr, list):
                 try:
                     fwd_addr = fwd_addr[cost]
                 except IndexError:
                     log.warning('Required private forwarding address index'
                                 ' is out of bounds. Wanted index %s '
                                 '- Have %s elements.',
                                 abs(cost), len(fwd_addr))
                     fwd_addr = fwd_addr[0]
                 cost = 1
             try:
                 fwd_addr = str(ip_interface(fwd_addr).ip)
             except ValueError:
                 log.debug('Forwarding address for %s-%s has no netmask: %s',
                           src, dst, fwd_addr)
             route.append((fwd_addr, str(cost)))
         yield prefix, route
Example #2
0
 def update_graph(self, new_graph):
     self.leader_watchdog.check_leader(self.get_leader())
     added_edges = new_graph.difference(self.graph)
     removed_edges = self.graph.difference(new_graph)
     node_prop_diff = {n: data
                       for n, data in new_graph.nodes_iter(data=True)
                       if n not in self.graph or
                       (data.viewitems() - self.graph.node[n].viewitems())}
     # Propagate differences
     if added_edges or removed_edges or node_prop_diff:
         log.debug('Pushing changes')
         for u, v in added_edges:
             self.for_all_listeners('add_edge', u, v,
                                    new_graph.export_edge_data(u, v))
         for u, v in removed_edges:
             self.for_all_listeners('remove_edge', u, v)
         if node_prop_diff:
             self.for_all_listeners('update_node_properties',
                                    **node_prop_diff)
         if CFG.getboolean(DEFAULTSECT, 'draw_graph'):
             new_graph.draw(CFG.get(DEFAULTSECT, 'graph_loc'))
         self.graph = new_graph
         log.info('LSA update yielded +%d -%d edges changes, '
                   '%d node property changes', len(added_edges),
                   len(removed_edges), len(node_prop_diff))
         self.for_all_listeners('commit')
 def add_edge(self, source, destination, metric):
     # metric is added twice to support backward-compat.
     self.igp_graph.add_edge(source, destination,
                             weight=int(metric), metric=int(metric))
     log.debug('Added edge: %s-%s@%s', source, destination, metric)
     # Only trigger an update if the link is bidirectional
     self.dirty = self.igp_graph.has_edge(destination, source)
 def add_edge(self, source, destination, properties={'metric': 1}):
     properties = sanitize_edge_data(properties)
     # metric is added twice to support backward-compat.
     self.igp_graph.add_edge(source, destination, properties)
     log.debug('Added edge: %s-%s@%s', source, destination, properties)
     # Only trigger an update if the link is bidirectional
     self.dirty = self.igp_graph.has_edge(destination, source)
Example #5
0
 def remove_redundant_fake_nodes(self):
     """Remove fake nodes that are useless (typically a path of redundant
     fake nodes that eventually got merged up to the penultimates nodes in
     the DAG)."""
     visited = set()
     # Start from destination and go back up the leaves
     to_visit = set(self.dag.predecessors_iter(self.dest))
     while to_visit:
         n = to_visit.pop()
         if n in visited:
             continue
         visited.add(n)
         node = self.node(n)
         # If we have a fake node
         if node.has_fake_node(subtype=Node.GLOBAL):
             # Is the LB redundant with the original SP ?
             succ = self.dag.successors(n)
             succ_dest_cost = self._p.default_cost(succ[0], self.dest)
             n_succ_cost = self._p.default_cost(n, succ[0])
             if node.lb + 1 == succ_dest_cost + n_succ_cost and\
                node.original_nhs == set(succ):
                 log.debug('Removing %s as it is redundant with the '
                           'original path [lb: %s, succ cost: %s, '
                           'n-succ cost: %s, succ: %s, orig succ: %s]',
                           n, node.lb, succ_dest_cost, n_succ_cost,
                           node.original_nhs, succ)
                 node.remove_fake_node()
             else:
                 log.debug('Keeping %s [lb: %s, succ cost: %s, '
                           'n-succ cost: %s, succ: %s, orig succ: %s]',
                           n, node.lb, succ_dest_cost, n_succ_cost,
                           node.original_nhs, succ)
         else:
             to_visit |= set(self.dag.predecessors_iter(n))
Example #6
0
 def del_ip(self, ip):
     """
     Remove an IP address from this port
     :param ip: an IPV4Address
     """
     log.debug('Removing %s from %s ip''s', ip, self.id)
     self.node.call('ip', 'addr', 'delete', ip.with_prefixlen)
Example #7
0
 def combine_ranges(self, n, s):
     """Attempt to combine the lb,ub interval between the two nodes"""
     node, succ = self.node(n), self.node(s)
     cost = self._p.default_cost(n, s)
     new_ub = min(node.ub - cost, succ.ub)
     new_lb = max(node.lb - cost, succ.lb)
     # Log these errors which should never happen
     # as propagation should prevent this
     if new_lb > succ.lb:
         log.error(
             'Merging %s into %s resulted in a LB increase from '
             '%s to %s (%s'
             's LB: %s, spt cost: %s)', n, s, succ.lb, new_lb, n, node.lb,
             cost)
     elif new_lb < succ.lb:
         log.error(
             'Merging %s into %s resulted in a LB decrease from '
             '%s to %s (%s'
             's LB: %s, spt cost: %s)', n, s, succ.lb, new_lb, n, node.lb,
             cost)
     # Report unfeasible merge
     if not self.valid_range(s, new_lb, new_ub):
         log.debug(
             'Merging %s into %s would lead to bounds of '
             ']%s, %s[, aborting', n, s, new_lb, new_ub)
         return None
     return new_lb, new_ub
Example #8
0
 def _test(self, igp_topo, fwd_dags, expected_lsa_count):
     solver = self.solver_provider()
     lsas = solver.solve(igp_topo, fwd_dags)
     log.debug('solved reqs with LSAs: %s', lsas)
     self.assertTrue(check_fwd_dags(fwd_dags, igp_topo, lsas, solver))
     log.debug('lsa count: %s, expected: %s', len(lsas), expected_lsa_count)
     self.assertTrue(len(lsas) == expected_lsa_count)
Example #9
0
 def compute_initial_ub(self):
     for n, node in self.nodes(Node.GLOBAL):
         if node.ub != DEFAULT_UB:
             log.debug('%s already has its UB set to %s', n, node.ub)
             continue
         node.ub = self._p.default_cost(n, self.dest)
         log.debug('Initial ub of %s set to %s', n, node.ub)
Example #10
0
 def _test(self, igp_topo, fwd_dags, expected_lsa_count):
     solver = self.solver_provider()
     lsas = solver.solve(igp_topo, fwd_dags)
     log.debug('solved reqs with LSAs: %s', lsas)
     self.assertTrue(check_fwd_dags(fwd_dags, igp_topo, lsas, solver))
     log.debug('lsa count: %s, expected: %s', len(lsas), expected_lsa_count)
     self.assertTrue(len(lsas) == expected_lsa_count)
Example #11
0
 def initialize_ecmp_deps(self):
     """Initialize ECMP dependencies"""
     for n, node in map(lambda x: (x[0], self.node(x[0])),
                        filter(lambda x: x[1] > 1,
                               self.dag.out_degree_iter())):
         if node.has_any_fake_node():
             log.debug('%s does ECMP and has a fake node', n)
             self.ecmp[n].add(n)
         else:
             f = []
             paths = self._p.default_path(n, self.dest)
             for p in paths:
                 # Try to find the first fake node for each path
                 for h in p[:-1]:
                     if self.node(h).has_any_fake_node():
                         f.add(h)
                         break
             if len(f) > 0 and len(f) < len(paths):
                 log.warning('%s does ECMP and has less downstream fake '
                             'nodes than paths (%s < %s), forcing it to '
                             'have a fake node.', n, len(f), len(paths))
                 node.fake_type = Node.GLOBAL
             elif f:
                 log.debug('Registering ECMP depencies on %s: %s', n, f)
                 for fake in f:
                     self.ecmp[fake].add(f)
Example #12
0
 def compute_initial_ub(self):
     for n, node in self.nodes(Node.GLOBAL):
         if node.ub != DEFAULT_UB:
             log.debug('%s already has its UB set to %s', n, node.ub)
             continue
         node.ub = self._p.default_cost(n, self.dest)
         log.debug('Initial ub of %s set to %s', n, node.ub)
 def add_edge(self, source, destination, properties={'metric': 1}):
     properties = sanitize_edge_data(properties)
     # metric is added twice to support backward-compat.
     self.igp_graph.add_edge(source, destination, properties)
     log.debug('Added edge: %s-%s@%s', source, destination, properties)
     # Only trigger an update if the link is bidirectional
     self.dirty = self.igp_graph.has_edge(destination, source)
Example #14
0
 def del_ip(self, ip):
     """
     Remove an IP address from this port
     :param ip: an IPV4Address
     """
     log.debug('Removing %s from %s ip''s', ip, self.id)
     self.node.call('ip', 'addr', 'delete', ip.with_prefixlen)
Example #15
0
def gen_physical_ports(port_list):
    """
    Find all enabled physical interfaces of this
    :param port_list: The list of all physical ports that should be analyzed
    :return: A list of Tuple (interface name, ip address)
            for each active physical interface
    """
    ports = []
    for port_name in port_list:
        try:
            ip = ip_interface(CFG.get(port_name, 'ip'))
            ports.append((port_name, ip))
        except ConfigError:
            try:
                out = subprocess.check_output(['ip', 'a', 'show', port_name])
                for line in out.splitlines():
                    if 'inet ' in line:
                        line = line.strip(' \t\n')
                        port_addr = ip_interface(line.split(' ')[1])
                        log.debug('Added physical port %s@%s',
                                  port_name, port_addr)
                        ports.append((port_name, port_addr))
                        break
                        # TODO support multiple IP/interface?
            except subprocess.CalledProcessError as e:
                log.exception(e)
    return ports
Example #16
0
 def advertize(self, prefix):
     """
     Advertize this fibbing point
     """
     log.debug('%s advertizes %s via %s', self.node.id, prefix, self.address)
     self.node.advertize(prefix.with_prefixlen, via=self.address, metric=self.metric)
     self.advertized = True
Example #17
0
def gen_physical_ports(port_list):
    """
    Find all enabled physical interfaces of this
    :param port_list: The list of all physical ports that should be analyzed
    :return: A list of Tuple (interface name, ip address)
            for each active physical interface
    """
    ports = []
    for port_name in port_list:
        try:
            out = subprocess.check_output(['ip', 'a', 'show', port_name])
            for line in out.splitlines():
                if 'inet ' in line:
                    line = line.strip(' \t\n')
                    # inet 130.104.228.87/25 brd 130.104.228.127 \
                    #                                 scope global dynamic eno1
                    port_addr = ip_interface(line.split(' ')[1])
                    log.debug('Added physical port %s@%s',
                              port_name, port_addr)
                    ports.append((port_name, port_addr))
                    break
                    # TODO support multiple IP/interface?
        except subprocess.CalledProcessError as e:
            log.exception(e)
    return ports
Example #18
0
 def initialize_ecmp_deps(self):
     """Initialize ECMP dependencies"""
     for n, node in map(
             lambda x: (x[0], self.node(x[0])),
             filter(lambda x: x[1] > 1, self.dag.out_degree_iter())):
         if node.has_any_fake_node():
             log.debug('%s does ECMP and has a fake node', n)
             self.ecmp[n].add(n)
         else:
             f = []
             paths = self._p.default_path(n, self.dest)
             for p in paths:
                 # Try to find the first fake node for each path
                 for h in p[:-1]:
                     if self.node(h).has_any_fake_node():
                         f.add(h)
                         break
             if len(f) > 0 and len(f) < len(paths):
                 log.warning(
                     '%s does ECMP and has less downstream fake '
                     'nodes than paths (%s < %s), forcing it to '
                     'have a fake node.', n, len(f), len(paths))
                 node.fake_type = Node.GLOBAL
             elif f:
                 log.debug('Registering ECMP depencies on %s: %s', n, f)
                 for fake in f:
                     self.ecmp[fake].add(f)
 def _get_diff_lsas(self):
     new_lsas = self.refresh_augmented_topo()
     log.debug('New LSA set: %s', new_lsas)
     to_add = new_lsas.difference(self.advertized_lsa)
     to_rem = self.advertized_lsa.difference(new_lsas)
     log.debug('Removing LSA set: %s', to_rem)
     self.advertized_lsa = new_lsas
     return to_add, to_rem
 def _get_diff_lsas(self):
     new_lsas = self.refresh_augmented_topo()
     log.debug('New LSA set: %s', new_lsas)
     to_add = new_lsas.difference(self.advertized_lsa)
     to_rem = self.advertized_lsa.difference(new_lsas)
     log.debug('Removing LSA set: %s', to_rem)
     self.advertized_lsa = new_lsas
     return to_add, to_rem
Example #21
0
def add_separate_destination_to_sinks(destination, input_topo, dag, cost=1):
    if destination in input_topo:
        destination = "Dest_" + destination
    for node in find_sink(dag):
        log.debug("Connecting %s to %s with cost %d", destination, node, cost)
        input_topo.add_edge(node, destination, weight=cost)
        dag.add_edge(node, destination)
    return destination
Example #22
0
 def create_ns(self):
     if os.path.exists(NSDIR) and ' %s ' % self.name in os.listdir(NSDIR):
         self.delete()
     err = _netns('add', self.name)
     if err != 0:
         log.error('Failed to create namespace %s', self.name)
     else:
         log.debug('Created namespace %s', self.name)
Example #23
0
 def create_ns(self):
     if os.path.exists(NSDIR) and ' %s ' % self.name in os.listdir(NSDIR):
         self.delete()
     err = _netns('add', self.name)
     if err != 0:
         log.error('Failed to create namespace %s', self.name)
     else:
         log.debug('Created namespace %s', self.name)
Example #24
0
 def advertize(self, prefix):
     """
     Advertize this fibbing point
     """
     log.debug('%s advertizes %s via %s',
               self.node.id, prefix, self.address)
     self.node.advertize(prefix.with_prefixlen, via=self.address,
                         metric=self.metric, ttl=self.ttl)
     self.advertized = True
 def boostrap_graph(self, graph):
     self.igp_graph.clear()
     for u, v, metric in graph:
         self.igp_graph.add_edge(u, v, weight=int(metric))
     log.debug('Bootstrapped graph with edges: %s', self.igp_graph.edges())
     log.debug('Sending initial lsa''s')
     if self.additional_routes:
         self.quagga_manager.add_static(self.additional_routes)
     self._refresh_lsas()
Example #26
0
def add_separate_destination_to_sinks(destination, input_topo, dag, cost=1):
    if destination in input_topo:
        destination = "Dest_" + destination
    for node in find_sink(dag):
        log.debug("Connecting %s to %s with cost %d",
                  destination, node, cost)
        input_topo.add_edge(node, destination, metric=cost)
        dag.add_edge(node, destination)
    return destination
Example #27
0
 def default_cost(self, u, v=None):
     """Return the cost of the pure IGP shortest path if Fibbing was not in
     use on the current network, between u and v or a dict of cost if v
     is None"""
     try:
         return self._get(self._default_dist, u, v)
     except KeyError as e:
         log.debug('%s had no path to %s (lookup key: %s)', u, v, e)
         return sys.maxint
Example #28
0
 def retract(self, address, advertize):
     try:
         point = self.attraction_points.pop(address)
         if advertize:
             point.retract(self.prefix)
         return point.node
     except KeyError:
         log.debug('Unkown attraction point %s for prefix %s', address, self.prefix)
         return None
Example #29
0
 def apply_secondary_addresses(self, graph):
     for src, dst in graph.router_links:
         try:
             graph[src][dst]['dst_address'] = self.private_addresses\
                                             .addresses_of(dst, src)
         except KeyError:
             log.debug('%(src)-%(dst)s does not yet exists on the graph'
                       ', ignoring private addresses.', locals())
             pass
Example #30
0
 def endpoints(self, lsdb):
     other_routers = []
     netdb = lsdb.lsdb(NetworkLSA)
     try:
         netlsa = netdb[self.dr_ip]
     except KeyError:
         log.debug('Cannot resolve network lsa for %s yet', self.dr_ip)
     else:
         other_routers.extend(netlsa.attached_routers)
     return other_routers
Example #31
0
 def create_link(self):
     """
     Create a veth link between the source and the destination ports
     """
     cmd = ['ip', 'link', 'add', self.src.id, 'type', 'veth', 'peer', 'name', self.dst.id]
     log.debug('Creating link: %s', cmd)
     err = subprocess.call(cmd)
     if err != 0:
         log.error('Failed to create veth link: %s', cmd)
         sys.exit(1)
 def add_edge(self, source, destination, metric):
     self.igp_graph.add_edge(source, destination, weight=int(metric))
     log.debug('Added edge: %s-%s@%s', source, destination, metric)
     try:
         self.igp_graph[destination][source]
     except KeyError:
         # Only trigger an update if the link is bidirectional
         pass
     else:
         self.dirty = True
Example #33
0
 def create_link(self):
     """
     Create a veth link between the source and the destination ports
     """
     cmd = ['ip', 'link', 'add', self.src.id, 'type', 'veth', 'peer', 'name', self.dst.id]
     log.debug('Creating link: %s', cmd)
     err = subprocess.call(cmd)
     if err != 0:
         log.error('Failed to create veth link: %s', cmd)
         sys.exit(1)
 def bootstrap_graph(self, graph, node_properties):
     self.igp_graph.clear()
     self.igp_graph.add_edges_from(graph)
     for _, _, d in self.igp_graph.edges_iter(data=True):
         sanitize_edge_data(d)
     self.update_node_properties(**node_properties)
     log.debug('Bootstrapped graph with edges: %s and properties: %s',
               self.igp_graph.edges(data=True), node_properties)
     self.received_initial_graph()
     self.graph_changed()
 def bootstrap_graph(self, graph, node_properties):
     self.igp_graph.clear()
     self.igp_graph.add_edges_from(graph)
     for _, _, d in self.igp_graph.edges_iter(data=True):
         sanitize_edge_data(d)
     self.update_node_properties(**node_properties)
     log.debug('Bootstrapped graph with edges: %s and properties: %s',
               self.igp_graph.edges(data=True), node_properties)
     self.received_initial_graph()
     self.graph_changed()
Example #36
0
 def endpoints(self, lsdb):
     other_routers = []
     netdb = lsdb.lsdb(NetworkLSA)
     try:
         netlsa = netdb[self.dr_ip]
     except KeyError:
         log.debug('Cannot resolve network lsa for %s yet', self.dr_ip)
     else:
         other_routers.extend(netlsa.attached_routers)
     return other_routers
Example #37
0
 def check_dest(self):
     """Check that the destination is present in the DAG and the graph"""
     log.debug('Checking dest in dag')
     ssu.add_dest_to_graph(self.dest, self.dag)
     log.debug('Checking dest in graph')
     ssu.add_dest_to_graph(self.dest, self.g,
                           edges_src=self.dag.predecessors,
                           spt=self._p,
                           metric=self.new_edge_metric,
                           node_data_gen=self.__new_dest)
Example #38
0
 def apply(self, graph, lsdb):
     if ip_address(self.routerid) in lsdb.exclude_net and \
        CFG.getboolean(DEFAULTSECT, 'exclude_fake_lsa'):
         log.debug('Skipping AS-external Fake LSA %s via %s',
                   self.address, [self.resolve_fwd_addr(r.fwd_addr)
                                  for r in self.routes])
         return
     for route in self.routes:
         graph.add_edge(self.resolve_fwd_addr(route.fwd_addr), self.prefix,
                        metric=route.metric)
Example #39
0
 def addresses_of(self, rid, f=None):
     """Return the list of private ip addresses for router id if f is None,
     else the list of forwarding addresses from f to rid"""
     try:
         return ([i for l in self._address_bindings[rid].itervalues()
                  for i in l]
                 if not f
                 else self._address_bindings[rid][f])
     except KeyError:
         log.debug('No private address for %s from %s', rid, f)
 def bootstrap_graph(self, graph, node_properties):
     self.igp_graph.clear()
     for u, v, metric in graph:
         self.igp_graph.add_edge(u, v, weight=int(metric))
     for n, data in node_properties.iteritems():
         self.igp_graph.node[n] = data
     log.debug('Bootstrapped graph with edges: %s and properties: %s',
               self.igp_graph.edges(data=True), node_properties)
     self.received_initial_graph()
     self.graph_changed()
Example #41
0
 def remove_route(self, network):
     """
     Remove a route
     :param network: The prefix to remove
     """
     net = ip_network(network)
     try:
         route = self.routes[net]
         self.remove_route_part(net, *[p for p in route])
     except KeyError:
         log.debug('No route for network %s', net)
Example #42
0
 def link(self, src, dst):
     """
     Create a veth Link between two nodes
     :param src: The source node of the link
     :param dst: The destination node of the link
     """
     log.debug('Linking %s to %s', src.id, dst.id)
     l = Link(src, dst)
     # Register the new link
     self.links.append(l)
     return l
Example #43
0
 def place_fake_nodes(self):
     for n in self.dag.nodes_iter():
         if self.g.out_degree(n) > 1:
             node = self.node(n)
             if self.needs_fake_node(node.original_nhs, node.forced_nhs):
                 node.add_fake_node()
                 log.debug('Adding a fake node on %s', n)
             else:
                 node.forced_nhs.clear()
                 log.debug('Skipping %s has it keeps the same successors',
                           n)
Example #44
0
 def place_fake_nodes(self):
     penultimate_nodes = self.dag.predecessors(self.dest)
     for n in self.dag.nodes_iter():
         if self.g.out_degree(n) > 1:  # Skip sinks
             node = self.node(n)
             node.add_fake_node()
             log.debug('Adding a fake node on %s', n)
             if n in penultimate_nodes:
                 node.lb = self._p.default_cost(n, self.dest) - 1
                 node.ub = node.lb + 2
                 log.debug('%s is a penultimate node, LB = cost to dest', n)
Example #45
0
def prepare_graph(g, req):
    """Copy the given graph and preset nodes attribute
    :type g: DiGraph
    :return: DiGraph
    :type req: {dest: fwd_req}
    :param req: The requirements for that graph"""
    log.debug('Copying graph')
    graph = g.copy()
    for n in graph.nodes():
        graph.node[n]['data'] = {key: Node(name=n) for key in req}
    return graph
Example #46
0
 def set_ip(self, ip):
     """
     Set this port's IP address
     :param ip: an IPV4Address
     """
     if self.ip_interface:
         # Remove the previous address if any
         self.del_ip(self.ip_interface)
     self.ip_interface = ip
     log.debug('Assigning %s to %s', ip, self.id)
     self.node.call('ip', 'addr', 'add', ip.with_prefixlen, 'dev', self.id)
 def refresh_lsas(self):
     """Refresh the set of LSAs that needs to be sent in the IGP,
     and instructs the southbound controller to update it if changed"""
     (to_add, to_rem) = self._get_diff_lsas()
     if not to_add and not to_rem:
         log.debug('Nothing to do for the current topology')
         return
     if to_rem:
         self.remove_lsa(*to_rem)
     if to_add:
         self.advertize_lsa(*to_add)
Example #48
0
 def check_dest(self):
     """Check that the destination is present in the DAG and the graph"""
     log.debug('Checking dest in dag')
     ssu.add_dest_to_graph(self.dest, self.dag)
     log.debug('Checking dest in graph')
     ssu.add_dest_to_graph(self.dest,
                           self.g,
                           edges_src=self.dag.predecessors,
                           spt=self._p,
                           metric=self.new_edge_metric,
                           node_data_gen=self.__new_dest)
Example #49
0
 def pipe(self, *args, **kwargs):
     cmd = ['ip', 'netns', 'exec', self.name]
     cmd.extend(args)
     log.debug(str(cmd))
     if 'stdin' not in kwargs:
         kwargs['stdin'] = subprocess.PIPE
     if 'stdout' not in kwargs:
         kwargs['stdout'] = subprocess.PIPE
     if 'stderr' not in kwargs:
         kwargs['stderr'] = subprocess.STDOUT
     return subprocess.Popen(cmd, **kwargs)
Example #50
0
 def remove_route(self, network):
     """
     Remove a route
     :param network: The prefix to remove
     """
     net = ip_network(network)
     try:
         route = self.routes[net]
         self.remove_route_part(net, *[p for p in route])
     except KeyError:
         log.debug('No route for network %s', net)
Example #51
0
 def place_fake_nodes(self):
     for n in self.dag.nodes_iter():
         if self.g.out_degree(n) > 1:
             node = self.node(n)
             if self.needs_fake_node(node.original_nhs, node.forced_nhs):
                 node.add_fake_node()
                 log.debug('Adding a fake node on %s', n)
             else:
                 node.forced_nhs.clear()
                 log.debug('Skipping %s has it keeps the same successors',
                           n)
Example #52
0
 def place_fake_nodes(self):
     penultimate_nodes = self.dag.predecessors(self.dest)
     for n in self.dag.nodes_iter():
         if self.g.out_degree(n) > 1:  # Skip sinks
             node = self.node(n)
             node.add_fake_node()
             log.debug('Adding a fake node on %s', n)
             if n in penultimate_nodes:
                 node.lb = self._p.default_cost(n, self.dest) - 1
                 node.ub = node.lb + 2
                 log.debug('%s is a penultimate node, LB = cost to dest', n)
Example #53
0
def prepare_graph(g, req):
    """Copy the given graph and preset nodes attribute
    :type g: DiGraph
    :return: DiGraph
    :type req: {dest: fwd_req}
    :param req: The requirements for that graph"""
    log.debug('Copying graph')
    graph = g.copy()
    for n in graph.nodes():
        graph.node[n]['data'] = {key: Node(name=n) for key in req}
    return graph
Example #54
0
 def refresh_augmented_topo(self):
     log.info('Solving topologies')
     if not self.json_proxy.alive() or not self.has_initial_topo:
         log.debug('Skipping as we do not yet have a topology')
         return self.advertized_lsa
     try:
         self.optimizer.solve(self.igp_graph, self.fwd_dags)
     except Exception as e:
         log.exception(e)
         return self.advertized_lsa
     else:
         return set(self.optimizer.get_fake_lsas())
Example #55
0
 def merge(self, n, succ, nh):
     """Try to merge n into its successor fake node, along the given path"""
     log.debug('Trying to merge %s into %s', n, succ)
     if not self.dag_include_spt(n, succ):
         return  # at least one IGP SP is not included in the DAG
     try:
         new_lb, new_ub = self.combine_ranges(n, succ)
         log.debug(
             'Merging %s into %s would result in bounds in %s set to '
             ']%s, %s[', n, succ, succ, new_lb, new_ub)
         self.apply_merge(n, succ, new_lb, new_ub, nh)
     except TypeError:  # Couldn't find a valid range, skip
         return