Loading src/opticalcontroller/OpticalController.py +8 −6 Original line number Diff line number Diff line Loading @@ -70,23 +70,25 @@ class AddLightpath(Resource): #@optical.route('/AddFlexLightpath/<string:src>/<string:dst>/<int:bitrate>') @optical.route('/AddFlexLightpath/<string:src>/<string:dst>/<int:bitrate>', defaults={"bidir": 1, "band": None}) defaults={"bidir": 1, "band": None, "obx_idx": None}) @optical.route('/AddFlexLightpath/<string:src>/<string:dst>/<int:bitrate>/<int:bidir>', defaults={"band": None}) @optical.route('/AddFlexLightpath/<string:src>/<string:dst>/<int:bitrate>/<int:bidir>/<int:band>',) defaults={"band": None, "obx_idx": None}) @optical.route('/AddFlexLightpath/<string:src>/<string:dst>/<int:bitrate>/<int:bidir>/<int:band>', defaults={"obx_idx": None}) @optical.route('/AddFlexLightpath/<string:src>/<string:dst>/<int:bitrate>/<int:bidir>/<int:band>/<int:obx_idx>') @optical.response(200, 'Success') @optical.response(404, 'Error, not found') class AddFlexLightpath(Resource): @staticmethod def put(src, dst, bitrate, bidir=1, band=None): def put(src, dst, bitrate, bidir=1, band=None, obx_idx = None): print("INFO: New FlexLightpath request from {} to {} with rate {} and band {}".format(src, dst, bitrate, band)) print("INFO: New MGON request from {} to {} with rate {} and band {}".format(src, dst, bitrate, band)) t0 = time.time()*1000.0 #if debug: # rsa.g.printGraph() if rsa is not None: flow_id, optical_band_id = rsa.rsa_fs_computation(src, dst, bitrate, bidir, band) flow_id, optical_band_id = rsa.rsa_fs_computation(src, dst, bitrate, bidir, band, obx_idx) if flow_id is not None: if rsa.db_flows[flow_id]["op-mode"] == 0: return 'No path found', 404 Loading src/opticalcontroller/RSA.py +53 −9 Original line number Diff line number Diff line Loading @@ -147,7 +147,31 @@ class RSA(): self.g.reset_graph() return links, path def get_slots(self, links, slots, optical_band_id=None): def compute_disjoint_path(self, src, dst, path1=None): if path1 == None: path1 = shortest_path(self.g, self.g.get_vertex(src), self.g.get_vertex(dst)) path = disjoint_path(self.g, src, dst, path1, False) print("INFO: Path from {} to {} with distance: {}".format(src, dst, self.g.get_vertex(dst).get_distance())) if debug: print(path) links = [] for i in range(0, len(path) - 1): s = path[i] if debug: print(s) if i < len(path) - 1: d = path[i + 1] link_id = "{}-{}".format(s, d) if debug: #print(link_id, self.links_dict[link_id]) print(link_id, self.get_link_by_name(link_id)) links.append(link_id) self.g.reset_graph() return links, path def get_slots(self, links, slots, optical_band_id=None, old_band_x=None): if isinstance(slots, int): val_c = slots Loading Loading @@ -246,6 +270,7 @@ class RSA(): l_slots[l] = combine(l_slots[l], consecutives(fib["l_slots"], val_l)) l_found = 1''' if optical_band_id is not None: print(f"NEW_DISJOINT: {self.optical_bands[optical_band_id]}") if "c_slots" in self.optical_bands[optical_band_id].keys(): if len(self.optical_bands[optical_band_id]["c_slots"]) > 0: a_c = c_sts Loading @@ -269,6 +294,14 @@ class RSA(): s_sts = common_slots(a_s, b_s) else: s_sts = [] if old_band_x == "c_slots": c_sts = [] l_sts = [] if old_band_x == "l_slots": c_sts = [] l_sts = [] if old_band_x == "s_slots": s_sts = [] return c_sts, l_sts, s_sts Loading Loading @@ -839,7 +872,7 @@ class RSA(): #self.db_flows[flow_id]["parent_opt_band"] = 0 #self.db_flows[flow_id]["new_optical_band"] = 0 def create_optical_band(self, links, path, bidir, num_slots): def create_optical_band(self, links, path, bidir, num_slots, old_band_x=None): print("INFO: Creating optical-band of {} slots".format(num_slots)) if self.opt_band_id == 0: self.opt_band_id += 1 Loading Loading @@ -888,8 +921,7 @@ class RSA(): if bidir: self.optical_bands[back_opt_band_id]["src"] = path[-1] ''' c_slots, l_slots, s_slots = self.get_slots(links, num_slots) c_slots, l_slots, s_slots = self.get_slots(links, num_slots, optical_band_id=None, old_band_x=old_band_x) if debug: print(c_slots) print(l_slots) Loading Loading @@ -991,7 +1023,7 @@ class RSA(): result.append(ob_id) return result def rsa_fs_computation(self, src, dst, rate, bidir, band): def rsa_fs_computation(self, src, dst, rate, bidir, band, bandx_id): if band is not None: num_slots_ob = map_band_to_slot(band) print(band, num_slots_ob) Loading @@ -999,11 +1031,23 @@ class RSA(): num_slots_ob = "full_band" if self.nodes_dict[src]["type"] == "OC-ROADM" and self.nodes_dict[dst]["type"] == "OC-ROADM": print("INFO: ROADM to ROADM connection") old_band_x = None if bandx_id != None: if bandx_id in self.optical_bands.keys(): path_x = self.optical_bands[bandx_id]["path"] old_band_x = self.optical_bands[bandx_id]["band_type"] links, path = self.compute_disjoint_path(src, dst, path_x) else: links, path = self.compute_disjoint_path(src, dst, None) if len(path) < 1: print("INFO: no disjoint path found, installing in the shortest path") links, path = self.compute_path(src, dst) else: links, path = self.compute_path(src, dst) if len(path) < 1: self.null_values_ob(self.opt_band_id) return self.opt_band_id, [] optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob) optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob, old_band_x) return None, optical_band_id print("INFO: TP to TP connection") if self.flow_id == 0: Loading src/opticalcontroller/dijkstra.py +157 −12 Original line number Diff line number Diff line Loading @@ -129,9 +129,20 @@ class Graph: self.vert_dict[frm].add_neighbor(self.vert_dict[to], [port_frm, w]) self.vert_dict[to].add_neighbor(self.vert_dict[frm], [port_to, w]) ''' def del_edge(self, frm, to, cost = 0): self.vert_dict[frm].del_neighbor(self.vert_dict[to]) self.vert_dict[to].del_neighbor(self.vert_dict[frm]) ''' def del_edge(self, frm, to, cost=0): if frm in self.vert_dict and to in self.vert_dict: v_from = self.vert_dict[frm] v_to = self.vert_dict[to] if v_to in v_from.adjacent: v_from.del_neighbor(v_to) if v_from in v_to.adjacent: v_to.del_neighbor(v_from) def get_vertices(self): return self.vert_dict.keys() Loading @@ -142,6 +153,45 @@ class Graph: def get_previous(self, current): return self.previous def copy(self): """ Returns a deep copy of the graph (vertices, edges, ports, and weights). """ new_graph = Graph() # First, create all vertices for node_id in self.vert_dict: new_graph.add_vertex(node_id) # Then, add all edges with the same attributes for v in self: for neighbor in v.get_connections(): frm = v.get_id() to = neighbor.get_id() port_frm = v.get_port(neighbor) port_to = neighbor.get_port(v) weight = v.get_weight(neighbor) # To avoid adding the same undirected edge twice if frm < to: new_graph.add_edge(frm, to, port_frm, port_to, weight) return new_graph def copy2(self): new_g = Graph() # Copy vertices for node_id in self.vert_dict: new_g.add_vertex(node_id) # Copy edges for frm in self.vert_dict: for to in self.vert_dict[frm].adjacent: port_frm, weight = self.vert_dict[frm].adjacent[to] port_to, _ = self.vert_dict[to].adjacent[frm] if not new_g.get_vertex(frm).adjacent.get(new_g.get_vertex(to)): new_g.add_edge(frm, to.get_id(), port_frm, port_to, weight) return new_g def shortest(v, path): if v.previous: path.append(v.previous.get_id()) Loading Loading @@ -198,6 +248,90 @@ def shortest_path(graph, src, dst): shortest(target, path) return path[::-1] def compute_disjoint_paths(graph, src, dst, k=2, disjoint_type="link", debug=False): """ Compute up to k disjoint shortest paths between src and dst using Dijkstra. disjoint_type: "link" (edge-disjoint) or "node" (vertex-disjoint) """ paths = [] removed_edges = [] # Keep track of removed edges removed_nodes = [] # Keep track of removed nodes for i in range(k): # Compute shortest path using the existing Dijkstra-based function path = shortest_path(graph, src, dst) # Stop if no valid path found if not path or len(path) < 2: if debug: print(f"[INFO] No more disjoint paths found after {i} iterations.") break paths.append(path) if debug: print(f"[INFO] Path {i+1}: {path}") # Depending on disjointness type, remove edges or nodes from graph if disjoint_type == "link": for u, v in zip(path[:-1], path[1:]): if debug: print(f" Removing edge {u}-{v}") removed_edges.append((u, v)) # Remove edge in both directions graph.del_edge(u, v) elif disjoint_type == "node": # Remove intermediate nodes (not source or destination) for n in path[1:-1]: if debug: print(f" Removing node {n}") removed_nodes.append(n) # Remove all edges involving this node v = graph.get_vertex(n) if v is not None: for neighbor in list(v.get_connections()): graph.del_edge(n, neighbor.get_id()) graph.del_Vertex(n) else: raise ValueError("disjoint_type must be 'link' or 'node'") # Reset distances & visited flags for the next run graph.reset_graph() if debug: print(f"[INFO] Found {len(paths)} disjoint paths.") return paths def disjoint_path(graph, src_id, dst_id, pathz, debug=False): g2 = graph.copy() src = g2.get_vertex(src_id) dst = g2.get_vertex(dst_id) removed_edges = [] # Keep track of removed edges removed_nodes = [] # Keep track of removed nodes for u, v in zip(pathz[:-1], pathz[1:]): if debug: print(f" Removing edge {u}-{v}") removed_edges.append((u, v)) # Remove edge in both directions g2.del_edge(u, v) # Compute shortest path using the existing Dijkstra-based function g2.reset_graph() pathx = shortest_path(g2, src, dst) # Stop if no valid path found if not pathx or len(pathx) < 2: if debug: print(f"[INFO] No more disjoint paths found.") return [] g2.reset_graph() return pathx if __name__ == '__main__': print("Testing Algo") Loading @@ -210,15 +344,15 @@ if __name__ == '__main__': g.add_vertex('e') g.add_vertex('f') g.add_edge('a', 'b', 7) g.add_edge('a', 'c', 9) g.add_edge('a', 'f', 14) g.add_edge('b', 'c', 10) g.add_edge('b', 'd', 15) g.add_edge('c', 'd', 11) g.add_edge('c', 'f', 2) g.add_edge('d', 'e', 6) g.add_edge('e', 'f', 9) g.add_edge('a', 'b', 1, 1, 7) g.add_edge('a', 'c', 2, 1, 9) g.add_edge('a', 'f', 3, 1, 14) g.add_edge('b', 'c', 2, 2, 10) g.add_edge('b', 'd', 3, 1, 15) g.add_edge('c', 'd', 3, 2, 11) g.add_edge('c', 'f', 4, 2, 2) g.add_edge('d', 'e', 4, 1, 6) g.add_edge('e', 'f', 2, 3, 9) """print ('Graph data:') Loading @@ -235,6 +369,17 @@ if __name__ == '__main__': path = [target.get_id()] shortest(target, path) print ('The shortest path : %s' %(path[::-1]))""" p = shortest_path(g, g.get_vertex('a'), g.get_vertex('e')) print(p) #print(g.printGraph()) pat = shortest_path(g, g.get_vertex('a'), g.get_vertex('e')) print(pat) #paths = compute_disjoint_paths(g, g.get_vertex('a'), g.get_vertex('e'), k=2, disjoint_type="link", debug=False) #paths = compute_disjoint_paths(g, g.get_vertex('a'), g.get_vertex('e'), k=2, disjoint_type="link", debug=False) #print(paths) path2 = compute_disjoint_path(g, 'a', 'e', pat, False) print(path2) pat = shortest_path(g, g.get_vertex('a'), g.get_vertex('d')) print(pat) path2 = compute_disjoint_path(g, 'a', 'd', pat, False) print(path2) No newline at end of file src/service/service/ServiceServiceServicerImpl.py +9 −5 Original line number Diff line number Diff line Loading @@ -288,6 +288,7 @@ class ServiceServiceServicerImpl(ServiceServiceServicer): ob_band = None oc_type = 1 bitrate = 100 dj_optical_band_id = None for constraint in service.service_constraints: if "bandwidth" in constraint.custom.constraint_type: bitrate = int(float(constraint.custom.constraint_value)) Loading @@ -296,19 +297,22 @@ class ServiceServiceServicerImpl(ServiceServiceServicer): elif "optical-band-width" in constraint.custom.constraint_type: ob_band = int(constraint.custom.constraint_value) elif "type" in constraint.custom.constraint_type: logging.info(f"TEEEEEEEEEEEEEEST {constraint.custom.constraint_type}={constraint.custom.constraint_value}") logging.info(f"{constraint.custom.constraint_type}={constraint.custom.constraint_value}") oc_type = OpticalServiceType(str(constraint.custom.constraint_value)) logging.info(f"TEEEEEEEEEEEEEEST {oc_type}") logging.info(f"{oc_type}") elif "disjoint_optical_band_id" in constraint.custom.constraint_type: logging.info(f"{constraint.custom.constraint_type}={constraint.custom.constraint_value}") dj_optical_band_id = int(constraint.custom.constraint_value) logging.info(f"{dj_optical_band_id}") reply_txt = "" # to get the reply form the optical module #multi-granular if oc_type == 1: reply_txt = add_flex_lightpath(src, dst, bitrate, bidir, ob_band) reply_txt = add_flex_lightpath(src, dst, bitrate, bidir, ob_band, dj_optical_band_id) elif oc_type == 2: reply_txt = add_lightpath(src, dst, bitrate, bidir) else: reply_txt = add_flex_lightpath(src, dst, bitrate, bidir, ob_band) reply_txt = add_flex_lightpath(src, dst, bitrate, bidir, ob_band, dj_optical_band_id) logging.info(f"TEEEEEEEEEEEEEEST {oc_type}") logging.info(f"POLIMI {reply_txt}") if reply_txt == None: Loading src/service/service/tools/OpticalTools.py +6 −2 Original line number Diff line number Diff line Loading @@ -137,11 +137,12 @@ def reconfig_flex_lightpath(flow_id) -> str: return reply_bid_txt def add_flex_lightpath(src, dst, bitrate, bidir, ob_band) -> str: def add_flex_lightpath(src, dst, bitrate, bidir, ob_band, dj_optical_band_id) -> str: if not TESTING: urlx = "" headers = {"Content-Type": "application/json"} base_url = get_optical_controller_base_url() if ob_band is None: if bidir is None: bidir = 1 Loading @@ -149,7 +150,10 @@ def add_flex_lightpath(src, dst, bitrate, bidir, ob_band) -> str: else: if bidir is None: bidir = 1 if dj_optical_band_id is None: urlx = "{:s}/AddFlexLightpath/{:s}/{:s}/{:s}/{:s}/{:s}".format(base_url, src, dst, str(bitrate), str(bidir), str(ob_band)) else: urlx = "{:s}/AddFlexLightpath/{:s}/{:s}/{:s}/{:s}/{:s}/{:s}".format(base_url, src, dst, str(bitrate), str(bidir), str(ob_band), str(dj_optical_band_id)) r = requests.put(urlx, headers=headers) print(f"addpathlight {r}") reply = r.text Loading Loading
src/opticalcontroller/OpticalController.py +8 −6 Original line number Diff line number Diff line Loading @@ -70,23 +70,25 @@ class AddLightpath(Resource): #@optical.route('/AddFlexLightpath/<string:src>/<string:dst>/<int:bitrate>') @optical.route('/AddFlexLightpath/<string:src>/<string:dst>/<int:bitrate>', defaults={"bidir": 1, "band": None}) defaults={"bidir": 1, "band": None, "obx_idx": None}) @optical.route('/AddFlexLightpath/<string:src>/<string:dst>/<int:bitrate>/<int:bidir>', defaults={"band": None}) @optical.route('/AddFlexLightpath/<string:src>/<string:dst>/<int:bitrate>/<int:bidir>/<int:band>',) defaults={"band": None, "obx_idx": None}) @optical.route('/AddFlexLightpath/<string:src>/<string:dst>/<int:bitrate>/<int:bidir>/<int:band>', defaults={"obx_idx": None}) @optical.route('/AddFlexLightpath/<string:src>/<string:dst>/<int:bitrate>/<int:bidir>/<int:band>/<int:obx_idx>') @optical.response(200, 'Success') @optical.response(404, 'Error, not found') class AddFlexLightpath(Resource): @staticmethod def put(src, dst, bitrate, bidir=1, band=None): def put(src, dst, bitrate, bidir=1, band=None, obx_idx = None): print("INFO: New FlexLightpath request from {} to {} with rate {} and band {}".format(src, dst, bitrate, band)) print("INFO: New MGON request from {} to {} with rate {} and band {}".format(src, dst, bitrate, band)) t0 = time.time()*1000.0 #if debug: # rsa.g.printGraph() if rsa is not None: flow_id, optical_band_id = rsa.rsa_fs_computation(src, dst, bitrate, bidir, band) flow_id, optical_band_id = rsa.rsa_fs_computation(src, dst, bitrate, bidir, band, obx_idx) if flow_id is not None: if rsa.db_flows[flow_id]["op-mode"] == 0: return 'No path found', 404 Loading
src/opticalcontroller/RSA.py +53 −9 Original line number Diff line number Diff line Loading @@ -147,7 +147,31 @@ class RSA(): self.g.reset_graph() return links, path def get_slots(self, links, slots, optical_band_id=None): def compute_disjoint_path(self, src, dst, path1=None): if path1 == None: path1 = shortest_path(self.g, self.g.get_vertex(src), self.g.get_vertex(dst)) path = disjoint_path(self.g, src, dst, path1, False) print("INFO: Path from {} to {} with distance: {}".format(src, dst, self.g.get_vertex(dst).get_distance())) if debug: print(path) links = [] for i in range(0, len(path) - 1): s = path[i] if debug: print(s) if i < len(path) - 1: d = path[i + 1] link_id = "{}-{}".format(s, d) if debug: #print(link_id, self.links_dict[link_id]) print(link_id, self.get_link_by_name(link_id)) links.append(link_id) self.g.reset_graph() return links, path def get_slots(self, links, slots, optical_band_id=None, old_band_x=None): if isinstance(slots, int): val_c = slots Loading Loading @@ -246,6 +270,7 @@ class RSA(): l_slots[l] = combine(l_slots[l], consecutives(fib["l_slots"], val_l)) l_found = 1''' if optical_band_id is not None: print(f"NEW_DISJOINT: {self.optical_bands[optical_band_id]}") if "c_slots" in self.optical_bands[optical_band_id].keys(): if len(self.optical_bands[optical_band_id]["c_slots"]) > 0: a_c = c_sts Loading @@ -269,6 +294,14 @@ class RSA(): s_sts = common_slots(a_s, b_s) else: s_sts = [] if old_band_x == "c_slots": c_sts = [] l_sts = [] if old_band_x == "l_slots": c_sts = [] l_sts = [] if old_band_x == "s_slots": s_sts = [] return c_sts, l_sts, s_sts Loading Loading @@ -839,7 +872,7 @@ class RSA(): #self.db_flows[flow_id]["parent_opt_band"] = 0 #self.db_flows[flow_id]["new_optical_band"] = 0 def create_optical_band(self, links, path, bidir, num_slots): def create_optical_band(self, links, path, bidir, num_slots, old_band_x=None): print("INFO: Creating optical-band of {} slots".format(num_slots)) if self.opt_band_id == 0: self.opt_band_id += 1 Loading Loading @@ -888,8 +921,7 @@ class RSA(): if bidir: self.optical_bands[back_opt_band_id]["src"] = path[-1] ''' c_slots, l_slots, s_slots = self.get_slots(links, num_slots) c_slots, l_slots, s_slots = self.get_slots(links, num_slots, optical_band_id=None, old_band_x=old_band_x) if debug: print(c_slots) print(l_slots) Loading Loading @@ -991,7 +1023,7 @@ class RSA(): result.append(ob_id) return result def rsa_fs_computation(self, src, dst, rate, bidir, band): def rsa_fs_computation(self, src, dst, rate, bidir, band, bandx_id): if band is not None: num_slots_ob = map_band_to_slot(band) print(band, num_slots_ob) Loading @@ -999,11 +1031,23 @@ class RSA(): num_slots_ob = "full_band" if self.nodes_dict[src]["type"] == "OC-ROADM" and self.nodes_dict[dst]["type"] == "OC-ROADM": print("INFO: ROADM to ROADM connection") old_band_x = None if bandx_id != None: if bandx_id in self.optical_bands.keys(): path_x = self.optical_bands[bandx_id]["path"] old_band_x = self.optical_bands[bandx_id]["band_type"] links, path = self.compute_disjoint_path(src, dst, path_x) else: links, path = self.compute_disjoint_path(src, dst, None) if len(path) < 1: print("INFO: no disjoint path found, installing in the shortest path") links, path = self.compute_path(src, dst) else: links, path = self.compute_path(src, dst) if len(path) < 1: self.null_values_ob(self.opt_band_id) return self.opt_band_id, [] optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob) optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob, old_band_x) return None, optical_band_id print("INFO: TP to TP connection") if self.flow_id == 0: Loading
src/opticalcontroller/dijkstra.py +157 −12 Original line number Diff line number Diff line Loading @@ -129,9 +129,20 @@ class Graph: self.vert_dict[frm].add_neighbor(self.vert_dict[to], [port_frm, w]) self.vert_dict[to].add_neighbor(self.vert_dict[frm], [port_to, w]) ''' def del_edge(self, frm, to, cost = 0): self.vert_dict[frm].del_neighbor(self.vert_dict[to]) self.vert_dict[to].del_neighbor(self.vert_dict[frm]) ''' def del_edge(self, frm, to, cost=0): if frm in self.vert_dict and to in self.vert_dict: v_from = self.vert_dict[frm] v_to = self.vert_dict[to] if v_to in v_from.adjacent: v_from.del_neighbor(v_to) if v_from in v_to.adjacent: v_to.del_neighbor(v_from) def get_vertices(self): return self.vert_dict.keys() Loading @@ -142,6 +153,45 @@ class Graph: def get_previous(self, current): return self.previous def copy(self): """ Returns a deep copy of the graph (vertices, edges, ports, and weights). """ new_graph = Graph() # First, create all vertices for node_id in self.vert_dict: new_graph.add_vertex(node_id) # Then, add all edges with the same attributes for v in self: for neighbor in v.get_connections(): frm = v.get_id() to = neighbor.get_id() port_frm = v.get_port(neighbor) port_to = neighbor.get_port(v) weight = v.get_weight(neighbor) # To avoid adding the same undirected edge twice if frm < to: new_graph.add_edge(frm, to, port_frm, port_to, weight) return new_graph def copy2(self): new_g = Graph() # Copy vertices for node_id in self.vert_dict: new_g.add_vertex(node_id) # Copy edges for frm in self.vert_dict: for to in self.vert_dict[frm].adjacent: port_frm, weight = self.vert_dict[frm].adjacent[to] port_to, _ = self.vert_dict[to].adjacent[frm] if not new_g.get_vertex(frm).adjacent.get(new_g.get_vertex(to)): new_g.add_edge(frm, to.get_id(), port_frm, port_to, weight) return new_g def shortest(v, path): if v.previous: path.append(v.previous.get_id()) Loading Loading @@ -198,6 +248,90 @@ def shortest_path(graph, src, dst): shortest(target, path) return path[::-1] def compute_disjoint_paths(graph, src, dst, k=2, disjoint_type="link", debug=False): """ Compute up to k disjoint shortest paths between src and dst using Dijkstra. disjoint_type: "link" (edge-disjoint) or "node" (vertex-disjoint) """ paths = [] removed_edges = [] # Keep track of removed edges removed_nodes = [] # Keep track of removed nodes for i in range(k): # Compute shortest path using the existing Dijkstra-based function path = shortest_path(graph, src, dst) # Stop if no valid path found if not path or len(path) < 2: if debug: print(f"[INFO] No more disjoint paths found after {i} iterations.") break paths.append(path) if debug: print(f"[INFO] Path {i+1}: {path}") # Depending on disjointness type, remove edges or nodes from graph if disjoint_type == "link": for u, v in zip(path[:-1], path[1:]): if debug: print(f" Removing edge {u}-{v}") removed_edges.append((u, v)) # Remove edge in both directions graph.del_edge(u, v) elif disjoint_type == "node": # Remove intermediate nodes (not source or destination) for n in path[1:-1]: if debug: print(f" Removing node {n}") removed_nodes.append(n) # Remove all edges involving this node v = graph.get_vertex(n) if v is not None: for neighbor in list(v.get_connections()): graph.del_edge(n, neighbor.get_id()) graph.del_Vertex(n) else: raise ValueError("disjoint_type must be 'link' or 'node'") # Reset distances & visited flags for the next run graph.reset_graph() if debug: print(f"[INFO] Found {len(paths)} disjoint paths.") return paths def disjoint_path(graph, src_id, dst_id, pathz, debug=False): g2 = graph.copy() src = g2.get_vertex(src_id) dst = g2.get_vertex(dst_id) removed_edges = [] # Keep track of removed edges removed_nodes = [] # Keep track of removed nodes for u, v in zip(pathz[:-1], pathz[1:]): if debug: print(f" Removing edge {u}-{v}") removed_edges.append((u, v)) # Remove edge in both directions g2.del_edge(u, v) # Compute shortest path using the existing Dijkstra-based function g2.reset_graph() pathx = shortest_path(g2, src, dst) # Stop if no valid path found if not pathx or len(pathx) < 2: if debug: print(f"[INFO] No more disjoint paths found.") return [] g2.reset_graph() return pathx if __name__ == '__main__': print("Testing Algo") Loading @@ -210,15 +344,15 @@ if __name__ == '__main__': g.add_vertex('e') g.add_vertex('f') g.add_edge('a', 'b', 7) g.add_edge('a', 'c', 9) g.add_edge('a', 'f', 14) g.add_edge('b', 'c', 10) g.add_edge('b', 'd', 15) g.add_edge('c', 'd', 11) g.add_edge('c', 'f', 2) g.add_edge('d', 'e', 6) g.add_edge('e', 'f', 9) g.add_edge('a', 'b', 1, 1, 7) g.add_edge('a', 'c', 2, 1, 9) g.add_edge('a', 'f', 3, 1, 14) g.add_edge('b', 'c', 2, 2, 10) g.add_edge('b', 'd', 3, 1, 15) g.add_edge('c', 'd', 3, 2, 11) g.add_edge('c', 'f', 4, 2, 2) g.add_edge('d', 'e', 4, 1, 6) g.add_edge('e', 'f', 2, 3, 9) """print ('Graph data:') Loading @@ -235,6 +369,17 @@ if __name__ == '__main__': path = [target.get_id()] shortest(target, path) print ('The shortest path : %s' %(path[::-1]))""" p = shortest_path(g, g.get_vertex('a'), g.get_vertex('e')) print(p) #print(g.printGraph()) pat = shortest_path(g, g.get_vertex('a'), g.get_vertex('e')) print(pat) #paths = compute_disjoint_paths(g, g.get_vertex('a'), g.get_vertex('e'), k=2, disjoint_type="link", debug=False) #paths = compute_disjoint_paths(g, g.get_vertex('a'), g.get_vertex('e'), k=2, disjoint_type="link", debug=False) #print(paths) path2 = compute_disjoint_path(g, 'a', 'e', pat, False) print(path2) pat = shortest_path(g, g.get_vertex('a'), g.get_vertex('d')) print(pat) path2 = compute_disjoint_path(g, 'a', 'd', pat, False) print(path2) No newline at end of file
src/service/service/ServiceServiceServicerImpl.py +9 −5 Original line number Diff line number Diff line Loading @@ -288,6 +288,7 @@ class ServiceServiceServicerImpl(ServiceServiceServicer): ob_band = None oc_type = 1 bitrate = 100 dj_optical_band_id = None for constraint in service.service_constraints: if "bandwidth" in constraint.custom.constraint_type: bitrate = int(float(constraint.custom.constraint_value)) Loading @@ -296,19 +297,22 @@ class ServiceServiceServicerImpl(ServiceServiceServicer): elif "optical-band-width" in constraint.custom.constraint_type: ob_band = int(constraint.custom.constraint_value) elif "type" in constraint.custom.constraint_type: logging.info(f"TEEEEEEEEEEEEEEST {constraint.custom.constraint_type}={constraint.custom.constraint_value}") logging.info(f"{constraint.custom.constraint_type}={constraint.custom.constraint_value}") oc_type = OpticalServiceType(str(constraint.custom.constraint_value)) logging.info(f"TEEEEEEEEEEEEEEST {oc_type}") logging.info(f"{oc_type}") elif "disjoint_optical_band_id" in constraint.custom.constraint_type: logging.info(f"{constraint.custom.constraint_type}={constraint.custom.constraint_value}") dj_optical_band_id = int(constraint.custom.constraint_value) logging.info(f"{dj_optical_band_id}") reply_txt = "" # to get the reply form the optical module #multi-granular if oc_type == 1: reply_txt = add_flex_lightpath(src, dst, bitrate, bidir, ob_band) reply_txt = add_flex_lightpath(src, dst, bitrate, bidir, ob_band, dj_optical_band_id) elif oc_type == 2: reply_txt = add_lightpath(src, dst, bitrate, bidir) else: reply_txt = add_flex_lightpath(src, dst, bitrate, bidir, ob_band) reply_txt = add_flex_lightpath(src, dst, bitrate, bidir, ob_band, dj_optical_band_id) logging.info(f"TEEEEEEEEEEEEEEST {oc_type}") logging.info(f"POLIMI {reply_txt}") if reply_txt == None: Loading
src/service/service/tools/OpticalTools.py +6 −2 Original line number Diff line number Diff line Loading @@ -137,11 +137,12 @@ def reconfig_flex_lightpath(flow_id) -> str: return reply_bid_txt def add_flex_lightpath(src, dst, bitrate, bidir, ob_band) -> str: def add_flex_lightpath(src, dst, bitrate, bidir, ob_band, dj_optical_band_id) -> str: if not TESTING: urlx = "" headers = {"Content-Type": "application/json"} base_url = get_optical_controller_base_url() if ob_band is None: if bidir is None: bidir = 1 Loading @@ -149,7 +150,10 @@ def add_flex_lightpath(src, dst, bitrate, bidir, ob_band) -> str: else: if bidir is None: bidir = 1 if dj_optical_band_id is None: urlx = "{:s}/AddFlexLightpath/{:s}/{:s}/{:s}/{:s}/{:s}".format(base_url, src, dst, str(bitrate), str(bidir), str(ob_band)) else: urlx = "{:s}/AddFlexLightpath/{:s}/{:s}/{:s}/{:s}/{:s}/{:s}".format(base_url, src, dst, str(bitrate), str(bidir), str(ob_band), str(dj_optical_band_id)) r = requests.put(urlx, headers=headers) print(f"addpathlight {r}") reply = r.text Loading