示例#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
示例#2
0
 def check_dest(self):
     """Check that the destination is present in the DAG and the graph"""
     dest_in_graph = self.dest in self.g
     log.debug('Checking for %s in the graph: %s', self.dest, dest_in_graph)
     if not dest_in_graph:
         log.info('Adding %s in the graph', self.dest)
         self.g.add_node(self.dest, data=Node())
         new_paths = {}
         new_paths_cost = {n: sys.maxint for n in self.g.nodes_iter()}
     dest_in_dag = self.dest in self.dag
     log.debug('Checking for the presence of %s the the DAG: %s',
               self.dest, dest_in_dag)
     if not dest_in_dag or not dest_in_graph:
         if not dest_in_dag:
             sinks = ssu.find_sink(self.dag)
         else:
             sinks = self.dag.predecessors(self.dest)
         for s in sinks:
             if not dest_in_dag:
                 log.info('Adding %s to %s in the dag', self.dest, s)
                 self.dag.add_edge(s, self.dest)
             if not dest_in_graph:
                 log.info('Adding edge (%s, %s) in the graph',
                          s, self.dest)
                 self.g.add_edge(s, self.dest, weight=self.new_edge_weight)
                 log.debug('Updating spt/cost accordingly')
                 for n in self.g.nodes_iter():
                     if n == self.dest:
                         new_paths[n] = [[n]]
                         new_paths_cost[n] = 0
                         continue
                     if not self.has_path(n, s):
                         continue
                     ns_cost = self.cost(n, s) + self.new_edge_weight
                     if ns_cost < new_paths_cost[n]:  # Created a new SP
                         ns_path = self.path(n, s)
                         new_paths_cost[n] = ns_cost
                         new_paths[n] = list(ssu.extend_paths_list(ns_path,
                                                                   self.dest
                                                                   ))
                     elif ns_cost == new_paths_cost:  # Created ECMP
                         ns_path = self.path(n, s)
                         new_paths[n].extend(ssu.extend_paths_list(ns_path,
                                                                   self.dest
                                                                   ))
     for n, p in new_paths.iteritems():  # Incrementally update the SPT
         self.register_path(n, self.dest, p, new_paths_cost[n])