Exemplo n.º 1
0
 def solve(self, topo, requirement_dags):
     # a list of tuples with info on the node to be attracted,
     # the forwarding address, the cost to be set in the fake LSA,
     # and the respective destinations
     self.fake_ospf_lsas = []
     self.reqs = requirement_dags
     self.igp_graph = topo
     self.igp_paths = ssu.all_shortest_paths(self.igp_graph)
     # process input forwarding DAGs, one at the time
     for dest, dag in requirement_dags.iteritems():
         logger.debug('Solving DAG for dest %s', dest)
         self.dest, self.dag = dest, dag
         self.add_dest_to_graphs(dest, dag)
         if dest not in topo:
             sinks = dag.predecessors(dest)
             for s in sinks:
                 logger.info('Adding edge (%s, %s) in the graph',
                             s, self.dest)
                 topo.add_edge(s, dest, weight=self.new_edge_weight)
             for n in topo.nodes_iter():
                 if n == dest:  # dest is a path in itself
                     self.igp_paths[n] = ([[n]], 0)
                     continue
                 paths = []
                 cost = sys.maxint
                 for s in sinks:
                     if s not in self.igp_paths[n][0]:  # no path to sink
                         continue
                     c = self.igp_paths[n][1][s]
                     p = self.igp_paths[n][0][s]
                     if c < cost:  # new spt
                         paths = list(ssu.extend_paths_list(p, dest))
                         cost = c
                     if c == cost:  # ecmp
                         paths.extend(ssu.extend_paths_list(p, dest))
                 if paths:
                     _t = self.igp_paths[n]
                     _t[0][dest] = paths
                     _t[1][dest] = cost
         self.complete_dag()
         # Add temporarily the destination to the igp graph and/or req dags
         if not self.solvable(dest, dag):
             continue
         for node in nx.topological_sort(dag, reverse=True)[1:]:
             nhs, original_nhs = self.nhs_for(node, dag, dest)
             if not self.require_fake_node(nhs, original_nhs):
                 logger.debug('%s does not require a fake node (%s - %s)',
                              node, nhs, original_nhs)
                 continue
             for req_nh in nhs:
                 logger.debug('Placing a fake node for nh %s', req_nh)
                 self.fake_ospf_lsas.append(ssu.LSA(node=node,
                                                    nh=req_nh,
                                                    cost=-1,
                                                    dest=dest))
     return self.fake_ospf_lsas
Exemplo n.º 2
0
 def solve(self, graph, requirements):
     """Compute the augmented topology for a given graph and a set of
     requirements.
     :type graph: DiGraph
     :type requirements: { dest: DiGraph }
     :param requirements: the set of requirement DAG on a per dest. basis
     :return: list of fake LSAs"""
     self.reqs = requirements
     log.info('Preparing IGP graph')
     self.g = prepare_graph(graph, requirements)
     log.info('Computing SPT')
     self._p = ssu.all_shortest_paths(self.g)
     lsa = []
     for dest, dag in requirements.iteritems():
         self.ecmp.clear()
         log.info('Evaluating requirement %s', dest)
         self.dest = dest
         self.dag = dag
         log.info('Ensuring the consistency of the DAG')
         self.check_dest()
         self.complete_dag()
         log.info('Computing original and required next-hop sets')
         for n, node in self.nodes():
             node.forced_nhs = set(self.dag.successors(n))
             node.original_nhs = set([p[1] for p in
                                      self.path(n, self.dest)])
         if not self.check_consistency():
             log.warning('Consistency check failed, skipping %s', dest)
             continue
         log.info('Placing initial fake nodes')
         self.place_fake_nodes()
         log.info('Initializing fake nodes')
         self.initialize_fake_nodes()
         log.info('Propagating initial lower bounds')
         self.propagate_lb()
         log.info('Reducing the augmented topology')
         self.merge_fake_nodes()
         log.info('Generating LSAs')
         lsas = self.create_fake_lsa()
         log.info('Solved the DAG for destination %s with LSA set: %s',
                  self.dest, lsas)
         lsa.extend(lsas)
     return lsa