From dee7cde1516480f37e78aeb9d74bd572031ea6bd Mon Sep 17 00:00:00 2001 From: sgambelluri Date: Thu, 15 Feb 2024 10:29:32 +0300 Subject: [PATCH 1/3] opticalcontroller component --- src/opticalcontroller/Dockerfile | 79 + src/opticalcontroller/OpticalController.py | 232 +++ src/opticalcontroller/README.md | 17 + src/opticalcontroller/RSA.py | 913 ++++++++ src/opticalcontroller/__init__.py | 0 src/opticalcontroller/dijsktra.py | 222 ++ src/opticalcontroller/images/topo.png | Bin 0 -> 30289 bytes src/opticalcontroller/json_files/nodes.json | 39 + .../json_files/optical_TFSworking.json | 486 +++++ .../json_files/optical_topoTFS.json | 1836 +++++++++++++++++ src/opticalcontroller/json_files/tfs.json | 1286 ++++++++++++ .../json_files/topo_2_links.json | 1530 ++++++++++++++ .../json_files/topology-optical.json | 252 +++ .../json_files/topology-optical2.json | 324 +++ src/opticalcontroller/requirements.in | 7 + src/opticalcontroller/tools.py | 175 ++ src/opticalcontroller/variables.py | 18 + 17 files changed, 7416 insertions(+) create mode 100644 src/opticalcontroller/Dockerfile create mode 100644 src/opticalcontroller/OpticalController.py create mode 100644 src/opticalcontroller/README.md create mode 100644 src/opticalcontroller/RSA.py create mode 100644 src/opticalcontroller/__init__.py create mode 100644 src/opticalcontroller/dijsktra.py create mode 100644 src/opticalcontroller/images/topo.png create mode 100644 src/opticalcontroller/json_files/nodes.json create mode 100644 src/opticalcontroller/json_files/optical_TFSworking.json create mode 100644 src/opticalcontroller/json_files/optical_topoTFS.json create mode 100644 src/opticalcontroller/json_files/tfs.json create mode 100644 src/opticalcontroller/json_files/topo_2_links.json create mode 100644 src/opticalcontroller/json_files/topology-optical.json create mode 100644 src/opticalcontroller/json_files/topology-optical2.json create mode 100644 src/opticalcontroller/requirements.in create mode 100644 src/opticalcontroller/tools.py create mode 100644 src/opticalcontroller/variables.py diff --git a/src/opticalcontroller/Dockerfile b/src/opticalcontroller/Dockerfile new file mode 100644 index 000000000..c3d886ab5 --- /dev/null +++ b/src/opticalcontroller/Dockerfile @@ -0,0 +1,79 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM python:3.9-slim + +# Install dependencies +RUN apt-get --yes --quiet --quiet update && \ + apt-get --yes --quiet --quiet install wget g++ && \ + rm -rf /var/lib/apt/lists/* + +# Set Python to show logs as they occur +ENV PYTHONUNBUFFERED=0 + +# Download the gRPC health probe +# RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \ +# wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \ +# chmod +x /bin/grpc_health_probe + + + + +# Get generic Python packages +RUN python3 -m pip install --upgrade pip +RUN python3 -m pip install --upgrade setuptools wheel +RUN python3 -m pip install --upgrade pip-tools + + + +COPY common_requirements.in common_requirements.in +RUN pip-compile --quiet --output-file=common_requirements.txt common_requirements.in +RUN python3 -m pip install -r common_requirements.txt + +RUN mkdir -p /var/teraflow/opticalcontroller + +WORKDIR /var/teraflow/opticalcontroller/common +COPY src/common/. ./ +RUN rm -rf proto + + +# Create proto sub-folder, copy .proto files, and generate Python code +RUN mkdir -p /var/teraflow/opticalcontroller/common/proto +WORKDIR /var/teraflow/opticalcontroller/common/proto +RUN touch __init__.py +COPY proto/*.proto ./ +RUN python3 -m grpc_tools.protoc -I=. --python_out=. --grpc_python_out=. *.proto +RUN rm *.proto +RUN find . -type f -exec sed -i -E 's/(import\ .*)_pb2/from . \1_pb2/g' {} \; + +# Create component sub-folder, get specific Python packages + + + +WORKDIR /var/teraflow/opticalcontroller +COPY src/opticalcontroller/requirements.in requirements.in +RUN pip-compile --quiet --output-file=requirements.txt requirements.in +RUN python3 -m pip install -r requirements.txt + +# Add component files into working directory +WORKDIR /var/teraflow/ + +COPY src/context/. context/ + +COPY src/opticalcontroller/. opticalcontroller/ +COPY src/context/. opticalcontroller/context/ + +# Start the service +WORKDIR /var/teraflow/opticalcontroller +ENTRYPOINT ["python", "OpticalController.py"] diff --git a/src/opticalcontroller/OpticalController.py b/src/opticalcontroller/OpticalController.py new file mode 100644 index 000000000..1acb67481 --- /dev/null +++ b/src/opticalcontroller/OpticalController.py @@ -0,0 +1,232 @@ +from flask import Flask +from flask import render_template +from flask_restplus import Resource, Api + +from tools import * +from variables import * +from RSA import RSA +import time +import logging + + +rsa = None +LOGGER = logging.getLogger(__name__) + +app = Flask(__name__) +api = Api(app, version='1.0', title='Optical controller API', + description='Rest API to configure OC Optical devices in TFS') +# app.config.from_object('config') +# appbuilder = AppBuilder(app, indexview=MyIndexView) +optical = api.namespace('OpticalTFS', description='TFS Optical APIs') + + +@app.route('/index') +def index(): + return render_template('index.html') + + +#@optical.route('/AddLightpath////') +@optical.route('/AddLightpath///') +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class AddLightpath(Resource): + @staticmethod + def put(src, dst, bitrate, bidir=1): + + LOGGER.info("INFO: New Lightpath request from {} to {} with rate {} ".format(src, dst, bitrate)) + t0 = time.time()*1000.0 + if debug: + rsa.g.printGraph() + + if rsa is not None: + flow_id = rsa.rsa_computation(src, dst, bitrate, bidir) + if rsa.db_flows[flow_id]["op-mode"] == 0: + return 'No path found', 404 + t1 = time.time()*1000.0 + elapsed = t1 - t0 + LOGGER.info("INFO: time elapsed = {} ms".format(elapsed)) + return rsa.db_flows[flow_id], 200 + else: + return "Error", 404 + + +#@optical.route('/AddFlexLightpath///') +@optical.route('/AddFlexLightpath///', + defaults={"bidir": 1, "band": None}) +@optical.route('/AddFlexLightpath////', + defaults={"band": None}) +@optical.route('/AddFlexLightpath/////',) +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class AddFlexLightpath(Resource): + @staticmethod + def put(src, dst, bitrate,bidir=1, band=None): + + print("INFO: New FlexLightpath request from {} to {} with rate {} ".format(src, dst, bitrate)) + LOGGER.info("INFO: New FlexLightpath request from {} to {} with rate {} ".format(src, dst, bitrate)) + 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) + print (f"flow_id {flow_id} and optical_band_id {optical_band_id} ") + if flow_id is not None: + if rsa.db_flows[flow_id]["op-mode"] == 0: + return 'No path found', 404 + t1 = time.time() * 1000.0 + elapsed = t1 - t0 + print("INFO: time elapsed = {} ms".format(elapsed)) + + return rsa.db_flows[flow_id], 200 + else: + if len(rsa.optical_bands[optical_band_id]["flows"]) == 0: + return 'No path found', 404 + else: + t1 = time.time() * 1000.0 + elapsed = t1 - t0 + LOGGER.info("INFO: time elapsed = {} ms".format(elapsed)) + + return rsa.optical_bands[optical_band_id], 200 + else: + return "Error", 404 + +@optical.route('/DelFlexLightpath/////') +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class DelLightpath(Resource): + @staticmethod + def delete(flow_id, src, dst, bitrate, o_band_id): + if flow_id in rsa.db_flows.keys(): + flow = rsa.db_flows[flow_id] + bidir = flow["bidir"] + match1 = flow["src"] == src and flow["dst"] == dst and flow["bitrate"] == bitrate + if bidir: + match2 = flow["src"] == dst and flow["dst"] == src and flow["bitrate"] == bitrate + if match1 or match2: + ob_id = flow["parent_opt_band"] + rsa.del_flow(flow, ob_id) + rsa.db_flows[flow_id]["is_active"] = False + rsa.optical_bands[ob_id]["served_lightpaths"].remove(flow_id) + if rsa.optical_bands[ob_id]["reverse_optical_band_id"] != 0: + rev_ob_id = rsa.optical_bands[ob_id]["reverse_optical_band_id"] + rsa.optical_bands[rev_ob_id]["served_lightpaths"].remove(flow_id) + + if debug: + LOGGER.info(links_dict) + return "flow {} deleted".format(flow_id), 200 + else: + return "flow {} not matching".format(flow_id), 404 + else: + if match1: + ob_id = flow["parent_opt_band"] + rsa.del_flow(flow, ob_id) + rsa.db_flows[flow_id]["is_active"] = False + rsa.optical_bands[ob_id]["served_lightpaths"].remove(flow_id) + if debug: + LOGGER.info(links_dict) + return "flow {} deleted".format(flow_id), 200 + else: + return "flow {} not matching".format(flow_id), 404 + else: + return "flow id {} does not exist".format(flow_id), 404 + + + +@optical.route('/DelLightpath////') +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class DelLightpath(Resource): + @staticmethod + def delete(flow_id, src, dst, bitrate): + if flow_id in rsa.db_flows.keys(): + flow = rsa.db_flows[flow_id] + match1 = flow["src"] == src and flow["dst"] == dst and flow["bitrate"] == bitrate + match2 = flow["src"] == dst and flow["dst"] == src and flow["bitrate"] == bitrate + if match1 or match2: + rsa.del_flow(flow) + rsa.db_flows[flow_id]["is_active"] = False + if debug: + LOGGER.info(links_dict) + return "flow {} deleted".format(flow_id), 200 + else: + return "flow {} not matching".format(flow_id), 404 + else: + return "flow id {} does not exist".format(flow_id), 404 + + +@optical.route('/GetLightpaths') +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class GetFlows(Resource): + @staticmethod + def get(): + try: + if debug: + LOGGER.info(rsa.db_flows) + return rsa.db_flows, 200 + except: + return "Error", 404 + +@optical.route('/GetOpticalBands') +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class GetBands(Resource): + @staticmethod + def get(): + print("Getting ") + LOGGER.info("Getting") + try: + if debug: + LOGGER.info(rsa.optical_bands) + return rsa.optical_bands, 200 + except: + return "Error", 404 + + +@optical.route('/GetOpticalBand/') +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class GetBand(Resource): + @staticmethod + def get(ob_id): + for ob_idx in rsa.optical_bands.keys(): + if str(ob_idx) == str(ob_id): + if debug: + LOGGER.info(rsa.optical_bands[ob_id]) + return rsa.optical_bands[ob_idx], 200 + return {}, 404 + + +@optical.route('/GetLinks') +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class GetFlows(Resource): + @staticmethod + def get(): + global links_dict + try: + if debug: + LOGGER.info(links_dict) + return links_dict, 200 + except: + return "Error", 404 + + +if __name__ == '__main__': + + + # Start metrics server + + LOGGER.info('Starting...') + + + + nodes_dict, links_dict = readTopologyData(nodes_json, topology_json) + + topologies,links= getTopology() + print ("topologies{} and devices {}".format(topologies,links)) + rsa = RSA(nodes_dict, links_dict) + LOGGER.info(rsa.init_link_slots(testing)) + + app.run(host='0.0.0.0', port=5022,debug=True) diff --git a/src/opticalcontroller/README.md b/src/opticalcontroller/README.md new file mode 100644 index 000000000..5fd94c59e --- /dev/null +++ b/src/opticalcontroller/README.md @@ -0,0 +1,17 @@ +# optical-controller +This a framework to implement the optical controller for the RMSA algorithm. +#create a venv +python -m venv venv + +in linux +source venv/Scripts/activate + +in windows +venv\Scripts\activate + +pip install -r requirements_opt.txt + +python OpticalController.py +![Reference Architecture](images/topo.png) + + diff --git a/src/opticalcontroller/RSA.py b/src/opticalcontroller/RSA.py new file mode 100644 index 000000000..47ddbe71c --- /dev/null +++ b/src/opticalcontroller/RSA.py @@ -0,0 +1,913 @@ +import dijsktra +from tools import * +from variables import * + + +class RSA(): + def __init__(self, nodes, links): + self.nodes_dict = nodes + self.links_dict = links + self.g = None + + self.flow_id = 0 + self.opt_band_id = 0 + self.db_flows = {} + self.initGraph() + self.c_slot_number = 0 + self.l_slot_number = 0 + self.s_slot_number = 0 + self.optical_bands = {} + + def init_link_slots(self, testing): + if not testing: + for l in self.links_dict["links"]: + for fib in l["optical_link"]["details"]["fibers"]: + #fib = self.links_dict[l]["fibers"][f] + if len(fib["c_slots"]) > 0: + fib["c_slots"] = list(range(0, Nc)) + if len(fib["l_slots"]) > 0: + fib["l_slots"] = list(range(0, Nl)) + if len(fib["s_slots"]) > 0: + fib["s_slots"] = list(range(0, Ns)) + if debug: + print(fib) + for l1 in self.links_dict["links"]: + + for fib1 in l1["optical_link"]["details"]["fibers"]: + #fib1 = self.links_dict[l1]["details"]["fibers"][f1] + + self.c_slot_number = len(fib1["c_slots"]) + self.l_slot_number = len(fib1["l_slots"]) + self.s_slot_number = len(fib1["s_slots"]) + + break + break + return "{},{},{}".format(self.c_slot_number, self.l_slot_number, self.s_slot_number) + + def initGraph(self): + self.g = dijsktra.Graph() + for n in self.nodes_dict: + self.g.add_vertex(n) + for l in self.links_dict["links"]: + if debug: + print(l) + [s, d] = l["optical_link"]["name"].split('-') + ps = l["optical_link"]["details"]["source"] + pd = l["optical_link"]["details"]["target"] + self.g.add_edge(s, d, ps, pd, 1) + + print("INFO: Graph initiated.") + if debug: + self.g.printGraph() + + def compute_path(self, src, dst): + path = dijsktra.shortest_path(self.g, self.g.get_vertex(src), self.g.get_vertex(dst)) + 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): + + if isinstance(slots, int): + val_c = slots + val_s = slots + val_l = slots + else: + val_c = self.c_slot_number + val_l = self.l_slot_number + val_s = self.s_slot_number + + c_sts = [] + l_sts = [] + s_sts = [] + c_slots = {} + l_slots = {} + s_slots = {} + add = "" + drop = "" + src_1, dst_1 = links[0].split('-') + src_2, dst_2 = links[-1].split('-') + if self.nodes_dict[src_1]["type"] == "OC-TP": + add = links[0] + if self.nodes_dict[dst_2]["type"] == "OC-TP": + drop = links[-1] + + for l in links: + c_slots[l] = [] + l_slots[l] = [] + s_slots[l] = [] + found = 0 + for link in self.links_dict["links"]: + if link["optical_link"]["name"] == l: + #for f in self.links_dict[l]['fibers'].keys(): + for fib in link["optical_link"]["details"]["fibers"]: + if l == add: + if 'used' in fib: + if fib["used"]: + #if debug: + print("WARNING!!!: link {}, fiber {} is already in use".format(l, fib["ID"])) + continue + if l == drop: + if 'used' in fib: + if fib["used"]: + #if debug: + print("WARNING!!!: link {}, fiber {} is already in use".format(l, fib["ID"])) + continue + if len(fib["c_slots"]) > 0: + c_slots[l] = combine(c_slots[l], consecutives(fib["c_slots"], val_c)) + if len(fib["l_slots"]) > 0: + l_slots[l] = combine(l_slots[l], consecutives(fib["l_slots"], val_l)) + if len(fib["s_slots"]) > 0: + s_slots[l] = combine(s_slots[l], consecutives(fib["s_slots"], val_s)) + if debug: + print(l, c_slots[l]) + found = 1 + if found == 0: + return [], [], [] + + keys = list(c_slots.keys()) + if debug: + print(len(keys)) + if debug: + print(keys[0]) + # intersection among the slots over all links + if len(keys) == 1: + c_sts = c_slots[keys[0]] + l_sts = l_slots[keys[0]] + s_sts = s_slots[keys[0]] + else: + for i in range(1, len(keys)): + if debug: + print(keys[i]) + # set a for the intersection + if i == 1: + a_c = c_slots[keys[i - 1]] + a_l = l_slots[keys[i - 1]] + a_s = s_slots[keys[i - 1]] + else: + a_c = c_sts + a_l = l_sts + a_s = s_sts + # set b for the intersection + b_c = c_slots[keys[i]] + b_l = l_slots[keys[i]] + b_s = s_slots[keys[i]] + + c_sts = common_slots(a_c, b_c) + l_sts = common_slots(a_l, b_l) + s_sts = common_slots(a_s, b_s) + if optical_band_id is not None: + 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 + b_c = self.optical_bands[optical_band_id]["c_slots"] + c_sts = common_slots(a_c, b_c) + else: + c_sts = [] + else: + c_sts = [] + if "l_slots" in self.optical_bands[optical_band_id].keys(): + if len(self.optical_bands[optical_band_id]["l_slots"]) > 0: + a_l = l_sts + b_l = self.optical_bands[optical_band_id]["l_slots"] + l_sts = common_slots(a_l, b_l) + else: + l_sts = [] + else: + l_sts = [] + if "s_slots" in self.optical_bands[optical_band_id].keys(): + if len(self.optical_bands[optical_band_id]["s_slots"]) > 0: + a_s = s_sts + b_s = self.optical_bands[optical_band_id]["s_slots"] + s_sts = common_slots(a_s, b_s) + else: + s_sts = [] + else: + s_sts = [] + + return c_sts, l_sts, s_sts + + def update_link(self, fib, slots, band): + for i in slots: + fib[band].remove(i) + if 'used' in fib: + fib['used'] = True + + def update_optical_band(self, optical_band_id, slots, band): + for i in slots: + self.optical_bands[optical_band_id][band].remove(i) + + def restore_link(self, fib, slots, band): + for i in slots: + fib[band].append(int(i)) + if 'used' in fib: + fib['used'] = False + fib[band].sort() + + def restore_optical_band(self, optical_band_id, slots, band): + for i in slots: + self.optical_bands[optical_band_id][band].append(int(i)) + self.optical_bands[optical_band_id][band].sort() + + def del_flow(self, flow, o_b_id = None): + flows = flow["flows"] + band = flow["band_type"] + slots = flow["slots"] + fiber_f = flow["fiber_forward"] + fiber_b = flow["fiber_backward"] + op = flow["op-mode"] + n_slots = flow["n_slots"] + path = flow["path"] + links = flow["links"] + bidir = flow["bidir"] + + for l in fiber_f.keys(): + if debug: + print(l) + print(fiber_f[l]) + #link = self.links_dict[l] + #f = fiber_f[l] + #fib = link['fibers'][f] + fib = self.get_fiber_details(l, fiber_f[l]) + if not list_in_list(slots, fib[band]): + self.restore_link(fib, slots, band) + if debug: + print(fib[band]) + if o_b_id is not None: + self.restore_optical_band(o_b_id, slots, band) + if bidir: + for rl in fiber_b.keys(): + if debug: + print(rl) + print(fiber_b[rl]) + #rlink = self.links_dict[rl] + #rf = fiber_b[rl] + #rfib = rlink['fibers'][rf] + rfib = self.get_fiber_details(rl, fiber_b[rl]) + if not list_in_list(slots, rfib[band]): + self.restore_link(rfib, slots, band) + if debug: + print(rfib[band]) + #changed according to TFS development + #if o_b_id is not None: + # rev_o_band_id = self.optical_bands[o_b_id]["reverse_optical_band_id"] + # self.restore_optical_band(rev_o_band_id, slots, band) + return True + + def get_fibers_forward(self, links, slots, band): + fiber_list = {} + add = links[0] + drop = links[-1] + print(links) + ''' + for link in self.links_dict["links"]: + if link["optical_link"]["name"] == l: + # for f in self.links_dict[l]['fibers'].keys(): + for fib in link["optical_link"]["details"]["fibers"]: + + ''' + for l in links: + for link in self.links_dict["links"]: + if link["optical_link"]["name"] == l: + for fib in link["optical_link"]["details"]["fibers"]: + #for f in self.links_dict[l]['fibers'].keys(): + #for fib in l["optical_link"]["details"]["fibers"]: + #fib = self.links_dict[l]['fibers'][f] + if l == add: + if 'used' in fib: + if fib["used"]: + if debug: + print("link {}, fiber {} is already in use".format(l, fib["ID"])) + continue + if l == drop: + if 'used' in fib: + if fib["used"]: + if debug: + print("link {}, fiber {} is already in use".format(l, fib["ID"])) + continue + if list_in_list(slots, fib[band]): + fiber_list[l] = fib["ID"] + self.update_link(fib, slots, band) + break + print("INFO: Path forward computation completed") + return fiber_list + + def get_link_by_name (self, key): + for link in self.links_dict["links"]: + if link["optical_link"]["name"] == key: + if debug: + print(link) + return link + + def get_fiber_details(self, link_key, fiber_id): + for link in self.links_dict["links"]: + if link["optical_link"]["name"] == link_key: + if debug: + print(link) + for fib in link["optical_link"]["details"]["fibers"]: + if fib["ID"] == fiber_id: + return fib + return None + + + def get_fibers_backward(self, links, fibers, slots, band): + fiber_list = {} + #r_drop = reverse_link(links[0]) + #r_add = reverse_link(links[-1]) + for l in fibers.keys(): + fib = self.get_fiber_details(l, fibers[l]) + ''' + link = self.get_link_by_name(l) + #port = self.links_dict[l]["fibers"][fibers[l]]["src_port"] + for fib in link["optical_link"]["details"]["fibers"]: + if fib["ID"] == fibers[l]: + ''' + port = fib["src_port"] + r_l = reverse_link(l) + r_link = self.get_link_by_name(r_l) + #for f in r_link["fibers"].keys(): + for r_fib in r_link["optical_link"]["details"]["fibers"]: + if r_fib["remote_peer_port"] == port: + if list_in_list(slots, r_fib[band]): + fiber_list[r_l] = r_fib["ID"] + self.update_link(r_fib, slots, band) + print("INFO: Path backward computation completed") + return fiber_list + + def select_slots_and_ports(self, links, n_slots, c, l, s, bidir): + if debug: + print(self.links_dict) + band, slots = slot_selection(c, l, s, n_slots, self.c_slot_number, self.l_slot_number, self.s_slot_number) + if band is None: + print("No slots available in the three bands") + return None, None, None + if debug: + print(band, slots) + fibers_f = self.get_fibers_forward(links, slots, band) + + fibers_b = [] + if bidir: + fibers_b = self.get_fibers_backward(links, fibers_f, slots, band) + if debug: + print("forward") + print(fibers_f) + print("backward") + print(fibers_b) + add = links[0] + drop = links[-1] + inport = "0" + outport = "0" + r_inport = "0" + r_outport = "0" + t_flows = {} + #if len(links) == 1: + + for lx in fibers_f: + if lx == add: + inport = "0" + r_outport = "0" + if lx == drop: + outport = "0" + r_inport = "0" + f = fibers_f[lx] + src, dst = lx.split("-") + fibx = self.get_fiber_details(lx, f) + #outport = self.links_dict[lx]['fibers'][f]["src_port"] + outport = fibx["src_port"] + + t_flows[src] = {} + t_flows[src]["f"] = {} + t_flows[src]["b"] = {} + t_flows[src]["f"] = {"in": inport, "out": outport} + + if bidir: + #r_inport = self.links_dict[lx]['fibers'][f]["local_peer_port"] + r_inport = fibx["local_peer_port"] + t_flows[src]["b"] = {"in": r_inport, "out": r_outport} + + #inport = self.links_dict[lx]['fibers'][f]["dst_port"] + inport = fibx["dst_port"] + if bidir: + #r_outport = self.links_dict[lx]['fibers'][f]["remote_peer_port"] + r_outport = fibx["remote_peer_port"] + t_flows[dst] = {} + t_flows[dst]["f"] = {} + t_flows[dst]["b"] = {} + t_flows[dst]["f"] = {"in": inport, "out": "0"} + if bidir: + t_flows[dst]["b"] = {"in": "0", "out": r_outport} + + if debug: + print(self.links_dict) + + if debug: + print(t_flows) + print("INFO: Flow matrix computed") + + return t_flows, band, slots, fibers_f, fibers_b + + def select_slots_and_ports_fs(self, links, n_slots, c, l, s, bidir, o_band_id): + if debug: + print(self.links_dict) + band, slots = slot_selection(c, l, s, n_slots, self.c_slot_number, self.l_slot_number, self.s_slot_number) + if band is None: + print("No slots available in the three bands") + return None, None, None, None, None + if debug: + print(band, slots) + fibers_f = self.get_fibers_forward(links, slots, band) + self.update_optical_band(o_band_id, slots, band) + fibers_b = [] + if bidir: + fibers_b = self.get_fibers_backward(links, fibers_f, slots, band) + ''' + + rev_o_band_id = self.optical_bands[o_band_id]["reverse_optical_band_id"] + self.update_optical_band(rev_o_band_id, slots, band) + ''' + if debug: + print("forward") + print(fibers_f) + if bidir: + print("backward") + print(fibers_b) + add = links[0] + drop = links[-1] + port_0 = "0" + + t_flows = {} + + #flows_add_side + f = fibers_f[add] + src, dst = add.split("-") + fibx = self.get_fiber_details(add, f) + #outport = self.links_dict[add]['fibers'][f]["src_port"] + outport = fibx["src_port"] + #T1 rules + t_flows[src] = {} + t_flows[src]["f"] = {} + t_flows[src]["b"] = {} + t_flows[src]["f"] = {"in": port_0, "out": outport} + if bidir: + #r_inport = self.links_dict[add]['fibers'][f]["local_peer_port"] + r_inport = fibx["local_peer_port"] + t_flows[src]["b"] = {"in": r_inport, "out": port_0} + + #R1 rules + t_flows[dst] = {} + t_flows[dst]["f"] = {} + t_flows[dst]["b"] = {} + #inport = self.links_dict[add]['fibers'][f]["dst_port"] + inport = fibx["dst_port"] + opt_band_src_port = self.optical_bands[o_band_id]["src_port"] + t_flows[dst]["f"] = {"in": inport, "out": opt_band_src_port} + #to modify to peer ports + if bidir: + #r_inport = self.links_dict[add]['fibers'][f]["local_peer_port"] + r_inport = fibx["local_peer_port"] + t_flows[src]["b"] = {"in": r_inport, "out": port_0} + if bidir: + rev_opt_band_dst_port = self.optical_bands[o_band_id]["rev_dst_port"] + #r_outport = self.links_dict[add]['fibers'][f]["remote_peer_port"] + r_outport = fibx["remote_peer_port"] + t_flows[dst]["b"] = {"in": rev_opt_band_dst_port, "out": r_outport} + + #flows_drop_side + # R2 rules + f = fibers_f[drop] + src, dst = drop.split("-") + fiby = self.get_fiber_details(drop, f) + #outport = self.links_dict[drop]['fibers'][f]["src_port"] + outport = fiby["src_port"] + + t_flows[src] = {} + t_flows[src]["f"] = {} + t_flows[src]["b"] = {} + opt_band_dst_port = self.optical_bands[o_band_id]["dst_port"] + t_flows[src]["f"] = {"in": opt_band_dst_port, "out": outport} + if bidir: + rev_opt_band_src_port = self.optical_bands[o_band_id]["rev_src_port"] + #r_inport = self.links_dict[drop]['fibers'][f]["local_peer_port"] + r_inport = fiby["local_peer_port"] + t_flows[src]["b"] = {"in": r_inport, "out": rev_opt_band_src_port} + t_flows[dst] = {} + t_flows[dst]["f"] = {} + t_flows[dst]["b"] = {} + #inport = self.links_dict[drop]['fibers'][f]["dst_port"] + inport = fiby["dst_port"] + t_flows[dst]["f"] = {"in": inport, "out": port_0} + if bidir: + #r_inport = self.links_dict[drop]['fibers'][f]["remote_peer_port"] + r_inport = fiby["remote_peer_port"] + t_flows[dst]["b"] = {"in": port_0, "out": r_inport} + + if debug: + print(self.links_dict) + + if debug: + print(t_flows) + print("INFO: Flow matrix computed for Flex Lightpath") + + return t_flows, band, slots, fibers_f, fibers_b + + def rsa_computation(self, src, dst, rate, bidir): + self.flow_id += 1 + self.db_flows[self.flow_id] = {} + self.db_flows[self.flow_id]["flow_id"] = self.flow_id + self.db_flows[self.flow_id]["src"] = src + self.db_flows[self.flow_id]["dst"] = dst + self.db_flows[self.flow_id]["bitrate"] = rate + self.db_flows[self.flow_id]["bidir"] = bidir + + links, path = self.compute_path(src, dst) + + if len(path) < 1: + self.null_values(self.flow_id) + return self.flow_id + op, num_slots = map_rate_to_slot(rate) + c_slots, l_slots, s_slots = self.get_slots(links, num_slots) + if debug: + print(c_slots) + print(l_slots) + print(s_slots) + if len(c_slots) > 0 or len(l_slots) > 0 or len(s_slots) > 0: + flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports(links, num_slots, c_slots, + l_slots, s_slots, bidir) + f0, band = freqency_converter(band_range, slots) + if debug: + print(f0, band) + print("INFO: RSA completed for normal wavelenght connection") + if flow_list is None: + self.null_values(self.flow_id) + return self.flow_id + slots_i = [] + for i in slots: + slots_i.append(int(i)) + # return links, path, flow_list, band_range, slots, fiber_f, fiber_b, op, num_slots, f0, band + # links, path, flows, bx, slots, fiber_f, fiber_b, op, n_slots, f0, band + self.db_flows[self.flow_id]["flows"] = flow_list + self.db_flows[self.flow_id]["band_type"] = band_range + self.db_flows[self.flow_id]["slots"] = slots_i + self.db_flows[self.flow_id]["fiber_forward"] = fiber_f + self.db_flows[self.flow_id]["fiber_backward"] = fiber_b + self.db_flows[self.flow_id]["op-mode"] = op + self.db_flows[self.flow_id]["n_slots"] = num_slots + self.db_flows[self.flow_id]["links"] = links + self.db_flows[self.flow_id]["path"] = path + self.db_flows[self.flow_id]["band"] = band + self.db_flows[self.flow_id]["freq"] = f0 + self.db_flows[self.flow_id]["is_active"] = True + return self.flow_id + + def null_values(self, flow_id): + self.db_flows[flow_id]["flows"] = {} + self.db_flows[flow_id]["band_type"] = "" + self.db_flows[flow_id]["slots"] = [] + self.db_flows[flow_id]["fiber_forward"] = [] + self.db_flows[flow_id]["fiber_backward"] = [] + self.db_flows[flow_id]["op-mode"] = 0 + self.db_flows[flow_id]["n_slots"] = 0 + self.db_flows[flow_id]["links"] = {} + self.db_flows[flow_id]["path"] = [] + self.db_flows[flow_id]["band"] = 0 + self.db_flows[flow_id]["freq"] = 0 + self.db_flows[flow_id]["is_active"] = False + + def null_values_ob(self, ob_id): + self.optical_bands[ob_id]["flows"] = {} + self.optical_bands[ob_id]["band_type"] = "" + #self.optical_bands[ob_id]["slots"] = [] + self.optical_bands[ob_id]["fiber_forward"] = [] + self.optical_bands[ob_id]["n_slots"] = 0 + self.optical_bands[ob_id]["links"] = {} + self.optical_bands[ob_id]["path"] = [] + self.optical_bands[ob_id]["band"] = 0 + self.optical_bands[ob_id]["freq"] = 0 + self.optical_bands[ob_id]["is_active"] = False + self.optical_bands[ob_id]["c_slots"] = [] + self.optical_bands[ob_id]["l_slots"] = [] + self.optical_bands[ob_id]["s_slots"] = [] + self.optical_bands[ob_id]["served_lightpaths"] = [] + self.optical_bands[ob_id]["reverse_optical_band_id"] = 0 + self.db_flows[self.flow_id]["parent_opt_band"] = 0 + self.db_flows[self.flow_id]["new_optical_band"] = 0 + + def create_optical_band(self, links, path, bidir, num_slots): + print("INFO: Creating optical-band of {} slots".format(num_slots)) + self.opt_band_id += 1 + forw_opt_band_id = self.opt_band_id + self.optical_bands[forw_opt_band_id] = {} + self.optical_bands[forw_opt_band_id]["optical_band_id"] = forw_opt_band_id + self.optical_bands[forw_opt_band_id]["bidir"] = bidir + ''' + back_opt_band_id = 0 + if bidir: + self.opt_band_id += 1 + back_opt_band_id = self.opt_band_id + self.optical_bands[back_opt_band_id] = {} + self.optical_bands[back_opt_band_id]["optical_band_id"] = back_opt_band_id + self.optical_bands[back_opt_band_id]["bidir"] = bidir + self.optical_bands[back_opt_band_id]["reverse_optical_band_id"] = forw_opt_band_id + self.optical_bands[forw_opt_band_id]["reverse_optical_band_id"] = back_opt_band_id + else: + self.optical_bands[forw_opt_band_id]["reverse_optical_band_id"] = 0 + ''' + op = 0 + temp_links = [] + #num_slots = "all" + if self.nodes_dict[path[0]]["type"] == "OC-TP": + add_link = links[0] + temp_links.append(add_link) + links.remove(add_link) + path.remove(path[0]) + self.optical_bands[forw_opt_band_id]["src"] = path[0] + ''' + if bidir: + self.optical_bands[back_opt_band_id]["dst"] = path[0] + ''' + if self.nodes_dict[path[-1]]["type"] == "OC-TP": + drop_link = links[-1] + temp_links.append(drop_link) + links.remove(drop_link) + path.remove(path[-1]) + self.optical_bands[forw_opt_band_id]["dst"] = path[-1] + ''' + if bidir: + self.optical_bands[back_opt_band_id]["src"] = path[-1] + ''' + + c_slots, l_slots, s_slots = self.get_slots(links, num_slots) + if debug: + print(c_slots) + print(l_slots) + print(s_slots) + if len(c_slots) > 0 or len(l_slots) > 0 or len(s_slots) > 0: + flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports(links, num_slots, c_slots, l_slots, s_slots, bidir) + f0, band = freqency_converter(band_range, slots) + print(flow_list, band_range, slots, fiber_f, fiber_b) + ''' + + flow_list_b = {} + rev_path = path.copy() + rev_path.reverse() + rev_links = reverse_links(links) + if bidir: + for dev_x in flow_list.keys(): + flow_list_b[dev_x] = {} + flow_list_b[dev_x]["f"] = flow_list[dev_x]["b"] + del flow_list[dev_x]["b"] + rev_path = path.copy() + ''' + if debug: + print(f0, band) + print("INFO: RSA completed for optical band") + if flow_list is None: + self.null_values(self.flow_id) + return self.flow_id, [] + slots_i = [] + for i in slots: + slots_i.append(int(i)) + + # return links, path, flow_list, band_range, slots, fiber_f, fiber_b, op, num_slots, f0, band + # links, path, flows, bx, slots, fiber_f, fiber_b, op, n_slots, f0, band + if len(flow_list) > 0: + src_port = flow_list[path[0]]['f']['out'] + dst_port = flow_list[path[-1]]['f']['in'] + print(flow_list) + if len(fiber_f.keys()) == 1: + link_x = list(fiber_f.keys())[0] + #fib_x = fiber_f[link_x] + #rev_dst_port = self.links_dict[link_x]['fibers'][fib_x]["local_peer_port"] + #rev_src_port = self.links_dict[link_x]['fibers'][fib_x]["remote_peer_port"] + fibx = self.get_fiber_details(link_x, fiber_f[link_x]) + rev_dst_port = fibx["local_peer_port"] + rev_src_port = fibx["remote_peer_port"] + else: + link_in = list(fiber_f.keys())[0] + link_out = list(fiber_f.keys())[-1] + fib_inx = self.get_fiber_details(link_in, fiber_f[link_in]) + fib_outx = self.get_fiber_details(link_out, fiber_f[link_out]) + rev_dst_port = fib_inx["local_peer_port"] + rev_src_port = fib_outx["remote_peer_port"] + + #fib_in = fiber_f[link_in] + #fib_out = fiber_f[link_out] + #rev_dst_port = self.links_dict[link_in]['fibers'][fib_in]["local_peer_port"] + #rev_src_port = self.links_dict[link_out]['fibers'][fib_out]["remote_peer_port"] + + self.optical_bands[forw_opt_band_id]["flows"] = flow_list + self.optical_bands[forw_opt_band_id]["band_type"] = band_range + self.optical_bands[forw_opt_band_id]["fiber_forward"] = fiber_f + self.optical_bands[forw_opt_band_id]["fiber_backward"] = fiber_b + self.optical_bands[forw_opt_band_id]["op-mode"] = op + self.optical_bands[forw_opt_band_id]["n_slots"] = num_slots + self.optical_bands[forw_opt_band_id]["links"] = links + self.optical_bands[forw_opt_band_id]["path"] = path + self.optical_bands[forw_opt_band_id]["band"] = band + self.optical_bands[forw_opt_band_id]["freq"] = f0 + self.optical_bands[forw_opt_band_id]["is_active"] = True + self.optical_bands[forw_opt_band_id]["src_port"] = src_port + self.optical_bands[forw_opt_band_id]["dst_port"] = dst_port + self.optical_bands[forw_opt_band_id]["rev_dst_port"] = rev_dst_port + self.optical_bands[forw_opt_band_id]["rev_src_port"] = rev_src_port + self.optical_bands[forw_opt_band_id][band_range] = slots_i + self.optical_bands[forw_opt_band_id]["served_lightpaths"] = [] + ''' + if bidir: + self.optical_bands[back_opt_band_id]["flows"] = flow_list_b + self.optical_bands[back_opt_band_id]["band_type"] = band_range + self.optical_bands[back_opt_band_id]["fiber_forward"] = fiber_b + # self.optical_bands[back_opt_band_id]["fiber_backward"] = fiber_b + self.optical_bands[back_opt_band_id]["op-mode"] = op + self.optical_bands[back_opt_band_id]["n_slots"] = num_slots + self.optical_bands[back_opt_band_id]["links"] = rev_links + self.optical_bands[back_opt_band_id]["path"] = rev_path + self.optical_bands[back_opt_band_id]["band"] = band + self.optical_bands[back_opt_band_id]["freq"] = f0 + self.optical_bands[back_opt_band_id]["is_active"] = True + self.optical_bands[back_opt_band_id]["src_port"] = rev_src_port + self.optical_bands[back_opt_band_id]["dst_port"] = rev_dst_port + self.optical_bands[back_opt_band_id][band_range] = slots_i.copy() + self.optical_bands[back_opt_band_id]["served_lightpaths"] = [] + ''' + + return forw_opt_band_id, temp_links + + def get_optical_bands(self, r_src, r_dst): + result = [] + for ob_id in self.optical_bands: + ob = self.optical_bands[ob_id] + if debug: + print(r_src, ob["src"]) + print(r_dst, ob["dst"]) + print(ob) + if ob["src"] == r_src and ob["dst"] == r_dst: + result.append(ob_id) + return result + + def rsa_fs_computation(self, src, dst, rate, bidir, band): + num_slots_ob = "full_band" + if band is not None: + num_slots_ob = map_band_to_slot(band) + print(band, num_slots_ob) + if self.nodes_dict[src]["type"] == "OC-ROADM" and self.nodes_dict[dst]["type"] == "OC-ROADM": + print("INFO: ROADM to ROADM connection") + links, path = self.compute_path(src, dst) + if len(path) < 1: + self.null_values_ob(self.opt_band_id) + return self.flow_id, [] + optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob) + return None, optical_band_id + print("INFO: TP to TP connection") + if band is None: + temp_links2 = [] + temp_path = [] + src_links = get_links_from_node(self.links_dict, src) + dst_links = get_links_to_node(self.links_dict, dst) + if len(src_links.keys()) >= 1: + temp_links2.append(list(src_links.keys())[0]) + if len(dst_links.keys()) >= 1: + temp_links2.append(list(dst_links.keys())[0]) + + if len(temp_links2) == 2: + [t_src, roadm_src] = temp_links2[0].split('-') + [roadm_dst, t_dst] = temp_links2[1].split('-') + temp_path.append(t_src) + temp_path.append(roadm_src) + temp_path.append(roadm_dst) + temp_path.append(t_dst) + existing_ob = self.get_optical_bands(roadm_src, roadm_dst) + self.flow_id += 1 + self.db_flows[self.flow_id] = {} + self.db_flows[self.flow_id]["flow_id"] = self.flow_id + self.db_flows[self.flow_id]["src"] = src + self.db_flows[self.flow_id]["dst"] = dst + self.db_flows[self.flow_id]["bitrate"] = rate + self.db_flows[self.flow_id]["bidir"] = bidir + + if len(existing_ob) > 0: + print("INFO: Evaluating existing OB {}".format(existing_ob)) + #first checking in existing OB + ob_found = 0 + for ob_id in existing_ob: + op, num_slots = map_rate_to_slot(rate) + if debug: + print(temp_links2) + c_slots, l_slots, s_slots = self.get_slots(temp_links2, num_slots, ob_id) + if debug: + print(c_slots) + print(l_slots) + print(s_slots) + if len(c_slots) >= num_slots or len(l_slots) >= num_slots or len(s_slots) >= num_slots: + flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs(temp_links2, num_slots, + c_slots, + l_slots, s_slots, bidir, + ob_id) + f0, band = freqency_converter(band_range, slots) + if debug: + print(f0, band) + print("INFO: RSA completed for Flex Lightpath with OB already in place") + if flow_list is None: + self.null_values(self.flow_id) + continue + slots_i = [] + for i in slots: + slots_i.append(int(i)) + # return links, path, flow_list, band_range, slots, fiber_f, fiber_b, op, num_slots, f0, band + # links, path, flows, bx, slots, fiber_f, fiber_b, op, n_slots, f0, band + self.db_flows[self.flow_id]["flows"] = flow_list + self.db_flows[self.flow_id]["band_type"] = band_range + self.db_flows[self.flow_id]["slots"] = slots_i + self.db_flows[self.flow_id]["fiber_forward"] = fiber_f + self.db_flows[self.flow_id]["fiber_backward"] = fiber_b + self.db_flows[self.flow_id]["op-mode"] = op + self.db_flows[self.flow_id]["n_slots"] = num_slots + self.db_flows[self.flow_id]["links"] = temp_links2 + self.db_flows[self.flow_id]["path"] = temp_path + self.db_flows[self.flow_id]["band"] = band + self.db_flows[self.flow_id]["freq"] = f0 + self.db_flows[self.flow_id]["is_active"] = True + self.db_flows[self.flow_id]["parent_opt_band"] = ob_id + self.db_flows[self.flow_id]["new_optical_band"] = 0 + self.optical_bands[ob_id]["served_lightpaths"].append(self.flow_id) + ''' + if bidir: + rev_ob_id = self.optical_bands[ob_id]["reverse_optical_band_id"] + self.optical_bands[rev_ob_id]["served_lightpaths"].append(self.flow_id) + ''' + return self.flow_id, ob_id + else: + print("not enough slots") + if band is None: + print("INFO: Not existing optical-band meeting the requirements") + else: + print("INFO: optical-band width specified") + #if no OB I create a new one + links, path = self.compute_path(src, dst) + optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob) + op, num_slots = map_rate_to_slot(rate) + self.flow_id += 1 + self.db_flows[self.flow_id] = {} + self.db_flows[self.flow_id]["flow_id"] = self.flow_id + self.db_flows[self.flow_id]["src"] = src + self.db_flows[self.flow_id]["dst"] = dst + self.db_flows[self.flow_id]["bitrate"] = rate + self.db_flows[self.flow_id]["bidir"] = bidir + + if debug: + print(temp_links) + c_slots, l_slots, s_slots = self.get_slots(temp_links, num_slots, optical_band_id) + if debug: + print(c_slots) + print(l_slots) + print(s_slots) + if len(c_slots) > 0 or len(l_slots) > 0 or len(s_slots) > 0: + flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs(temp_links, num_slots, c_slots, + l_slots, s_slots, bidir, optical_band_id) + f0, band = freqency_converter(band_range, slots) + if debug: + print(f0, band) + print("INFO: RSA completed for FLex Lightpath with new OB") + if flow_list is None: + self.null_values(self.flow_id) + return self.flow_id, optical_band_id + slots_i = [] + for i in slots: + slots_i.append(int(i)) + + self.db_flows[self.flow_id]["flows"] = flow_list + self.db_flows[self.flow_id]["band_type"] = band_range + self.db_flows[self.flow_id]["slots"] = slots_i + self.db_flows[self.flow_id]["fiber_forward"] = fiber_f + self.db_flows[self.flow_id]["fiber_backward"] = fiber_b + self.db_flows[self.flow_id]["op-mode"] = op + self.db_flows[self.flow_id]["n_slots"] = num_slots + self.db_flows[self.flow_id]["links"] = temp_links + self.db_flows[self.flow_id]["path"] = path + self.db_flows[self.flow_id]["band"] = band + self.db_flows[self.flow_id]["freq"] = f0 + self.db_flows[self.flow_id]["is_active"] = True + self.db_flows[self.flow_id]["parent_opt_band"] = optical_band_id + self.db_flows[self.flow_id]["new_optical_band"] = 1 + self.optical_bands[optical_band_id]["served_lightpaths"].append(self.flow_id) + ''' + if bidir: + rev_ob_id = self.optical_bands[optical_band_id]["reverse_optical_band_id"] + self.optical_bands[rev_ob_id]["served_lightpaths"].append(self.flow_id) + ''' + return self.flow_id, optical_band_id diff --git a/src/opticalcontroller/__init__.py b/src/opticalcontroller/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/opticalcontroller/dijsktra.py b/src/opticalcontroller/dijsktra.py new file mode 100644 index 000000000..5be78c624 --- /dev/null +++ b/src/opticalcontroller/dijsktra.py @@ -0,0 +1,222 @@ +import sys + +class Vertex: + def __init__(self, node): + self.id = node + self.adjacent = {} + # Set distance to infinity for all nodes + self.distance = float("inf") + # Mark all nodes unvisited + self.visited = False + # Predecessor + self.previous = None + + # heapq compara gli item nella coda usando <= per vedere ci sono duplciati: + # se ho una coda di tuple, + # compara il primo elemento della prima tupla nella coda con il primo elemento della seconda tupla nella coda + # se sono diversi si ferma, se sono uguali continua + # la tupla nel caso in esame è: (v.get_distance(),v) + # se due nodi hanno stessa distanza, heapq procede a comparare v: Vertex(). + # Va quindi definita una politica per confrontare i Vertex + def __lt__(self, other): + if self.id < other.id: + return True + else: + return False + + def __le__(self, other): + if self.id <= other.id: + return True + else: + return False + + def add_neighbor(self, neighbor, port): + self.adjacent[neighbor] = port + + def del_neighbor(self, neighbor): + self.adjacent.pop(neighbor) + + def get_connections(self): + return self.adjacent.keys() + + def get_id(self): + return self.id + + def get_port(self, neighbor): + return self.adjacent[neighbor][0] + + def get_weight(self, neighbor): + return self.adjacent[neighbor][1] + + def set_distance(self, dist): + self.distance = dist + + def get_distance(self): + return self.distance + + def set_previous(self, prev): + self.previous = prev + + def set_visited(self): + self.visited = True + + def reset_vertex(self): + self.visited = False + self.previous = None + self.distance = float("inf") + + def __str__(self): + return str(self.id) + ' adjacent: ' + str([x.id for x in self.adjacent]) + +class Graph: + def __init__(self): + self.vert_dict = {} + self.num_vertices = 0 + + def __iter__(self): + return iter(self.vert_dict.values()) + + def reset_graph(self): + for n in self.vert_dict: + self.get_vertex(n).reset_vertex() + + def printGraph(self): + for v in self: + for w in v.get_connections(): + vid = v.get_id() + wid = w.get_id() + print ('( %s , %s, %s, %s, %s, %s)' % ( vid, wid, v.get_port(w), w.get_port(v), v.get_weight(w), w.get_weight(v))) + + def add_vertex(self, node): + self.num_vertices = self.num_vertices + 1 + new_vertex = Vertex(node) + self.vert_dict[node] = new_vertex + return new_vertex + + def del_Vertex(self, node): + self.vert_dict.pop(node) + + def get_vertex(self, n): + if n in self.vert_dict: + return self.vert_dict[n] + else: + return None + + def add_edge(self, frm, to, port_frm, port_to,w): + if frm not in self.vert_dict: + self.add_vertex(frm) + if to not in self.vert_dict: + self.add_vertex(to) + + 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 get_vertices(self): + return self.vert_dict.keys() + + def set_previous(self, current): + self.previous = current + + def get_previous(self, current): + return self.previous + +def shortest(v, path): + if v.previous: + path.append(v.previous.get_id()) + shortest(v.previous, path) + return + +import heapq + +def dijkstra(aGraph, start): + """print ('''Dijkstra's shortest path''')""" + # Set the distance for the start node to zero + start.set_distance(0) + + # Put tuple pair into the priority queue + unvisited_queue = [(v.get_distance(),v) for v in aGraph] + #priority queue->costruisce un albero in cui ogni nodo parent ha ha un valore <= di ogni child + #heappop prende il valore più piccolo, nel caso di dikstra, il nodo più vicino + heapq.heapify(unvisited_queue) + + while len(unvisited_queue): + # Pops a vertex with the smallest distance + uv = heapq.heappop(unvisited_queue) + current = uv[1] + current.set_visited() + + #for next in v.adjacent: + for next in current.adjacent: + # if visited, skip + if next.visited: + continue + new_dist = current.get_distance() + current.get_weight(next) + + if new_dist < next.get_distance(): + next.set_distance(new_dist) + next.set_previous(current) + """print ('updated : current = %s next = %s new_dist = %s' \ + %(current.get_id(), next.get_id(), next.get_distance()))""" + else: + """print ('not updated : current = %s next = %s new_dist = %s' \ + %(current.get_id(), next.get_id(), next.get_distance()))""" + + # Rebuild heap + # 1. Pop every item + while len(unvisited_queue): + heapq.heappop(unvisited_queue) + # 2. Put all vertices not visited into the queue + unvisited_queue = [(v.get_distance(),v) for v in aGraph if not v.visited] + heapq.heapify(unvisited_queue) + +def shortest_path(graph, src, dst): + dijkstra(graph, src) + target = dst + path = [target.get_id()] + shortest(target, path) + return path[::-1] + +if __name__ == '__main__': + + print("Testing Algo") + g = Graph() + + g.add_vertex('a') + g.add_vertex('b') + g.add_vertex('c') + g.add_vertex('d') + 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) + + + """print ('Graph data:') + for v in g: + for w in v.get_connections(): + vid = v.get_id() + wid = w.get_id() + print ('( %s , %s, %3d)' % ( vid, wid, v.get_weight(w))) + + + dijkstra(g, g.get_vertex('a')) + + target = g.get_vertex('e') + 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) \ No newline at end of file diff --git a/src/opticalcontroller/images/topo.png b/src/opticalcontroller/images/topo.png new file mode 100644 index 0000000000000000000000000000000000000000..216e1360b3caecd68285ca8b69fd498049dcbf79 GIT binary patch literal 30289 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" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "T1" + } + }, + "endpoint_uuid": { + "uuid": "1" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "R1" + } + }, + "endpoint_uuid": { + "uuid": "12" + } + } + ], + "optical_link": { + "name": "T1-R1", + "details": { + "length": 0, + "source": "muxT", + "target": "srgR", + "fibers": [ + { + "ID": "M1", + "length": 0, + "src_port": "1", + "dst_port": "2001", + "local_peer_port": "1", + "remote_peer_port": "1001", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + { + "ID": "M2", + "length": 0, + "src_port": "2", + "dst_port": "2002", + "local_peer_port": "2", + "remote_peer_port": "1002", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + { + "ID": "M3", + "length": 0, + "src_port": "3", + "dst_port": "2003", + "local_peer_port": "3", + "remote_peer_port": "1003", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + } + ] + } + } + }, + { + "link_id": { + "link_uuid": { + "uuid": "R1->T1" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "R1" + } + }, + "endpoint_uuid": { + "uuid": "2" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "T1" + } + }, + "endpoint_uuid": { + "uuid": "1" + } + } + ], + "optical_link": { + "name": "R1-T1", + "details": { + "length": 0, + "source": "srgT", + "target": "muxT", + "fibers": [ + { + "ID": "M1", + "length": 0, + "src_port": "1001", + "dst_port": "1", + "local_peer_port": "2001", + "remote_peer_port": "1", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + { + "ID": "M2", + "length": 0, + "src_port": "1002", + "dst_port": "2", + "local_peer_port": "2002", + "remote_peer_port": "2", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + { + "ID": "M3", + "length": 0, + "src_port": "1003", + "dst_port": "3", + "local_peer_port": "2003", + "remote_peer_port": "3", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + } + ] + } + } + }, + { + "link_id": { + "link_uuid": { + "uuid": "R1->R2" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "R1" + } + }, + "endpoint_uuid": { + "uuid": "13" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "R2" + } + }, + "endpoint_uuid": { + "uuid": "24" + } + } + ], + "optical_link": { + "name": "R1-R2", + "details": { + "length": 0, + "source": "D1", + "target": "D1", + "fibers": [ + { + "ID": "D11", + "length": 0, + "src_port": "13", + "dst_port": "24", + "local_peer_port": "23", + "remote_peer_port": "14", + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + } + ] + } + } + }, + { + "link_id": { + "link_uuid": { + "uuid": "R2->R1" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "R2" + } + }, + "endpoint_uuid": { + "uuid": "14" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "R1" + } + }, + "endpoint_uuid": { + "uuid": "23" + } + } + ], + "optical_link": { + "name": "R2-R1", + "details": { + "length": 0, + "source": "D1", + "target": "D1", + "fibers": [ + { + "ID": "D11", + "length": 0, + "src_port": "14", + "dst_port": "23", + "local_peer_port": "24", + "remote_peer_port": "13", + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + } + ] + } + } + }, + { + "link_id": { + "link_uuid": { + "uuid": "T2->R2" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "T2" + } + }, + "endpoint_uuid": { + "uuid": "1" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "R2" + } + }, + "endpoint_uuid": { + "uuid": "1001" + } + } + ], + "optical_link": { + "name": "T2-R2", + "details": { + "length": 0, + "source": "srgT", + "target": "muxT", + "fibers": [ + { + "ID": "M1", + "length": 0, + "src_port": "1", + "dst_port": "1001", + "local_peer_port": "1", + "remote_peer_port": "2001", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + { + "ID": "M2", + "length": 0, + "src_port": "2", + "dst_port": "1002", + "local_peer_port": "2", + "remote_peer_port": "2002", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + { + "ID": "M3", + "length": 0, + "src_port": "3", + "dst_port": "1003", + "local_peer_port": "3", + "remote_peer_port": "2003", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + } + ] + } + } + }, + { + "link_id": { + "link_uuid": { + "uuid": "R2->T2" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "R2" + } + }, + "endpoint_uuid": { + "uuid": "5" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "T2" + } + }, + "endpoint_uuid": { + "uuid": "6" + } + } + ], + "optical_link": { + "name": "R2-T2", + "details": { + "length": 0, + "source": "srgT", + "target": "muxT", + "fibers": [ + { + "ID": "M1", + "length": 0, + "src_port": "1001", + "dst_port": "1", + "local_peer_port": "2001", + "remote_peer_port": "1", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + { + "ID": "M2", + "length": 0, + "src_port": "1002", + "dst_port": "2", + "local_peer_port": "2002", + "remote_peer_port": "2", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + { + "ID": "M3", + "length": 0, + "src_port": "1003", + "dst_port": "3", + "local_peer_port": "2003", + "remote_peer_port": "3", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/src/opticalcontroller/json_files/topo_2_links.json b/src/opticalcontroller/json_files/topo_2_links.json new file mode 100644 index 000000000..02165938c --- /dev/null +++ b/src/opticalcontroller/json_files/topo_2_links.json @@ -0,0 +1,1530 @@ +{ + "R1-R3": { + "length": 80, + "source": "d2", + "target": "d1", + "fibers": { + "d2-1": { + "length": 80, + "src_port": "103", + "dst_port": "201", + "local_peer_port": "203", + "remote_peer_port": "101", + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + "d2-2": { + "length": 80, + "src_port": "104", + "dst_port": "202", + "local_peer_port": "204", + "remote_peer_port": "102", + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + } + } + }, + "R3-R1": { + "length": 80, + "source": "d1", + "target": "d2", + "fibers": { + "d1-1": { + "length": 80, + "src_port": "101", + "dst_port": "203", + "local_peer_port": "201", + "remote_peer_port": "103", + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + "d1-2": { + "length": 80, + "src_port": "102", + "dst_port": "204", + "local_peer_port": "202", + "remote_peer_port": "104", + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + } + } + }, + "R2-R3": { + "length": 80, + "source": "d2", + "target": "d2", + "fibers": { + "d2-1": { + "length": 80, + "src_port": "103", + "dst_port": "203", + "local_peer_port": "203", + "remote_peer_port": "103", + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + "d2-2": { + "length": 80, + "src_port": "104", + "dst_port": "204", + "local_peer_port": "204", + "remote_peer_port": "104", + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + } + } + }, + "R3-R2": { + "length": 80, + "source": "d2", + "target": "d2", + "fibers": { + "d2-1": { + "length": 80, + "src_port": "103", + "dst_port": "203", + "local_peer_port": "203", + "remote_peer_port": "103", + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + "d2-2": { + "length": 80, + "src_port": "104", + "dst_port": "204", + "local_peer_port": "204", + "remote_peer_port": "104", + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + } + } + }, + "T1-R1": { + "length": 0, + "source": "muxT", + "target": "srgR", + "fibers": { + "M1": { + "length": 0, + "src_port": "1", + "dst_port": "2001", + "local_peer_port": "1", + "remote_peer_port": "1001", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + "M2": { + "length": 0, + "src_port": "2", + "dst_port": "2002", + "local_peer_port": "2", + "remote_peer_port": "1002", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + "M3": { + "length": 0, + "src_port": "3", + "dst_port": "2003", + "local_peer_port": "3", + "remote_peer_port": "1003", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + } + } + }, + "R1-T1": { + "length": 0, + "source": "srgT", + "target": "muxR", + "fibers": { + "S1": { + "length": 0, + "src_port": "1001", + "dst_port": "1", + "local_peer_port": "2001", + "remote_peer_port": "1", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + "S2": { + "length": 0, + "src_port": "1002", + "dst_port": "2", + "local_peer_port": "2002", + "remote_peer_port": "2", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + "S3": { + "length": 0, + "src_port": "1003", + "dst_port": "3", + "local_peer_port": "2003", + "remote_peer_port": "3", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + } + } + }, + "T2-R2": { + "length": 0, + "source": "muxT", + "target": "srgR", + "fibers": { + "M1": { + "length": 0, + "src_port": "1", + "dst_port": "2001", + "local_peer_port": "1", + "remote_peer_port": "1001", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + "M2": { + "length": 0, + "src_port": "2", + "dst_port": "2002", + "local_peer_port": "2", + "remote_peer_port": "1002", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + "M3": { + "length": 0, + "src_port": "3", + "dst_port": "2003", + "local_peer_port": "3", + "remote_peer_port": "1003", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + } + } + }, + "R2-T2": { + "length": 0, + "source": "srgT", + "target": "muxR", + "fibers": { + "S1": { + "length": 0, + "src_port": "1001", + "dst_port": "1", + "local_peer_port": "2001", + "remote_peer_port": "1", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + "S2": { + "length": 0, + "src_port": "1002", + "dst_port": "2", + "local_peer_port": "2002", + "remote_peer_port": "2", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + }, + "S3": { + "length": 0, + "src_port": "1003", + "dst_port": "3", + "local_peer_port": "2003", + "remote_peer_port": "3", + "used": false, + "c_slots": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "l_slots": [ + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120 + ], + "s_slots": [ + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520 + ] + } + } + } +} diff --git a/src/opticalcontroller/json_files/topology-optical.json b/src/opticalcontroller/json_files/topology-optical.json new file mode 100644 index 000000000..e2453b654 --- /dev/null +++ b/src/opticalcontroller/json_files/topology-optical.json @@ -0,0 +1,252 @@ +{ + "r1-r2": { + "length": 80, + "source" : "d1", + "target" : "d1", + "fibers" : { + "d1-1": { + "src_port": "1T", + "dst_port": "1R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "d1-2":{ + "src_port": "2T", + "dst_port": "2R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "r2-r1": { + "length": 80, + "source" : "d1", + "target" : "d1", + "fibers" : { + "d1-1" : { + "src_port": "1T", + "dst_port": "1R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "d1-2" : { + "src_port": "2T", + "dst_port": "2R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "r1-r3": { + "length": 80, + "source" : "d2", + "target" : "d1", + "fibers" : { + "d2-1":{ + "src_port": "3T", + "dst_port": "1R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "d2-2":{ + "src_port": "4T", + "dst_port": "2R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "r3-r1": { + "length": 80, + "source" : "d1", + "target" : "d2", + "fibers" : { + "d1-1": { + "src_port": "1T", + "dst_port": "3R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "d1-2": { + "src_port": "2T", + "dst_port": "4R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "r2-r3": { + "length": 80, + "source" : "d2", + "target" : "d2", + "fibers" : { + "d2-1": { + "src_port": "3T", + "dst_port": "3R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "d2-2": { + "src_port": "4T", + "dst_port": "4R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "r3-r2": { + "length": 80, + "source" : "d2", + "target" : "d2", + "fibers" : { + "d2-1": { + "src_port": "3T", + "dst_port": "3R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "d2-2":{ + "src_port": "4T", + "dst_port": "4R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "t1-r1": { + "length": 0, + "source" : "muxT", + "target" : "srgR", + "fibers" : { + "M1": { + "src_port": "1", + "dst_port": "101R", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "M2": { + "src_port": "2", + "dst_port": "102R", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "M3": { + "src_port": "3", + "dst_port": "103R", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "r1-t1": { + "length": 0, + "source" : "srgT", + "target" : "muxR", + "fibers" : { + "S1": { + "src_port": "101T", + "dst_port": "1", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "S2": { + "src_port": "102T", + "dst_port": "2", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "S3": { + "src_port": "103T", + "dst_port": "3", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "t2-r2": { + "length": 0, + "source" : "muxT", + "target" : "srgR", + "fibers" : { + "M1": { + "src_port": "1", + "dst_port": "101R", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "M2": { + "src_port": "2", + "dst_port": "102R", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "M3": { + "src_port": "3", + "dst_port": "103R", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "r2-t2": { + "length": 0, + "source" : "srgT", + "target" : "muxR", + "fibers" : { + "S1": { + "src_port": "101T", + "dst_port": "1", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "S2": { + "src_port": "102T", + "dst_port": "2", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "S3": { + "src_port": "103T", + "dst_port": "3", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + } +} diff --git a/src/opticalcontroller/json_files/topology-optical2.json b/src/opticalcontroller/json_files/topology-optical2.json new file mode 100644 index 000000000..fe8e9866b --- /dev/null +++ b/src/opticalcontroller/json_files/topology-optical2.json @@ -0,0 +1,324 @@ +{ + "r1-r2": { + "length": 80, + "source" : "d1", + "target" : "d1", + "fibers" : { + "d1-1": { + "length": 80, + "src_port": "1T", + "dst_port": "1R", + "local_peer_port": "1R", + "remote_peer_port": "1T", + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + }, + "d1-2":{ + "length": 80, + "src_port": "2T", + "dst_port": "2R", + "local_peer_port": "2R", + "remote_peer_port": "2T", + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + } + } + }, + "r2-r1": { + "length": 80, + "source" : "d1", + "target" : "d1", + "fibers" : { + "d1-1" : { + "length": 80, + "src_port": "1T", + "dst_port": "1R", + "local_peer_port": "1R", + "remote_peer_port": "1T", + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + }, + "d1-2" : { + "length": 80, + "src_port": "2T", + "dst_port": "2R", + "local_peer_port": "2R", + "remote_peer_port": "2T", + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + } + } + }, + "r1-r3": { + "length": 80, + "source" : "d2", + "target" : "d1", + "fibers" : { + "d2-1":{ + "length": 80, + "src_port": "3T", + "dst_port": "1R", + "local_peer_port": "3R", + "remote_peer_port": "1T", + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + }, + "d2-2":{ + "length": 80, + "src_port": "4T", + "dst_port": "2R", + "local_peer_port": "4R", + "remote_peer_port": "2T", + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + } + } + }, + "r3-r1": { + "length": 80, + "source" : "d1", + "target" : "d2", + "fibers" : { + "d1-1": { + "length": 80, + "src_port": "1T", + "dst_port": "3R", + "local_peer_port": "1R", + "remote_peer_port": "3T", + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + }, + "d1-2": { + "length": 80, + "src_port": "2T", + "dst_port": "4R", + "local_peer_port": "2R", + "remote_peer_port": "4T", + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + } + } + }, + "r2-r3": { + "length": 80, + "source" : "d2", + "target" : "d2", + "fibers" : { + "d2-1": { + "length": 80, + "src_port": "3T", + "dst_port": "3R", + "local_peer_port": "3R", + "remote_peer_port": "3T", + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + }, + "d2-2": { + "length": 80, + "src_port": "4T", + "dst_port": "4R", + "local_peer_port": "4R", + "remote_peer_port": "4T", + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + } + } + }, + "r3-r2": { + "length": 80, + "source" : "d2", + "target" : "d2", + "fibers" : { + "d2-1": { + "length": 80, + "src_port": "3T", + "dst_port": "3R", + "local_peer_port": "3R", + "remote_peer_port": "3T", + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + }, + "d2-2":{ + "length": 80, + "src_port": "4T", + "dst_port": "4R", + "local_peer_port": "4R", + "remote_peer_port": "4T", + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + } + } + }, + "t1-r1": { + "length": 0, + "source" : "muxT", + "target" : "srgR", + "fibers" : { + "M1": { + "length": 0, + "src_port": "1", + "dst_port": "101R", + "local_peer_port": "1", + "remote_peer_port": "101T", + "used": false, + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + }, + "M2": { + "length": 0, + "src_port": "2", + "dst_port": "102R", + "local_peer_port": "2", + "remote_peer_port": "102T", + "used": false, + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + }, + "M3": { + "length": 0, + "src_port": "3", + "dst_port": "103R", + "local_peer_port": "3", + "remote_peer_port": "103T", + "used": false, + "c_slots": [], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + } + } + }, + "r1-t1": { + "length": 0, + "source" : "srgT", + "target" : "muxR", + "fibers" : { + "S1": { + "length": 0, + "src_port": "101T", + "dst_port": "1", + "local_peer_port": "101R", + "remote_peer_port": "1", + "used": false, + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + }, + "S2": { + "length": 0, + "src_port": "102T", + "dst_port": "2", + "local_peer_port": "102T", + "remote_peer_port": "2", + "used": false, + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + }, + "S3": { + "length": 0, + "src_port": "103T", + "dst_port": "3", + "local_peer_port": "103R", + "remote_peer_port": "3", + "used": false, + "c_slots": [], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + } + } + }, + "t2-r2": { + "length": 0, + "source" : "muxT", + "target" : "srgR", + "fibers" : { + "M1": { + "length": 0, + "src_port": "1", + "dst_port": "101R", + "local_peer_port": "1", + "remote_peer_port": "101T", + "used": false, + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + }, + "M2": { + "length": 0, + "src_port": "2", + "dst_port": "102R", + "local_peer_port": "2", + "remote_peer_port": "102T", + "used": false, + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + }, + "M3": { + "length": 0, + "src_port": "3", + "dst_port": "103R", + "local_peer_port": "3", + "remote_peer_port": "103T", + "used": false, + "c_slots": [], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + } + } + }, + "r2-t2": { + "length": 0, + "source" : "srgT", + "target" : "muxR", + "fibers" : { + "S1": { + "length": 0, + "src_port": "101T", + "dst_port": "1", + "local_peer_port": "101R", + "remote_peer_port": "1", + "used": false, + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + }, + "S2": { + "length": 0, + "src_port": "102T", + "dst_port": "2", + "local_peer_port": "102R", + "remote_peer_port": "2", + "used": false, + "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + }, + "S3": { + "length": 0, + "src_port": "103T", + "dst_port": "3", + "local_peer_port": "103R", + "remote_peer_port": "3", + "used": false, + "c_slots": [], + "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], + "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] + } + } + } +} diff --git a/src/opticalcontroller/requirements.in b/src/opticalcontroller/requirements.in new file mode 100644 index 000000000..e4b8abe1b --- /dev/null +++ b/src/opticalcontroller/requirements.in @@ -0,0 +1,7 @@ +Flask==1.1.2 +flask-restplus==0.13.0 +itsdangerous==1.1.0 +Jinja2==2.11.3 +MarkupSafe==1.1.1 +numpy==1.23.0 +Werkzeug==0.16.1 diff --git a/src/opticalcontroller/tools.py b/src/opticalcontroller/tools.py new file mode 100644 index 000000000..d91240d45 --- /dev/null +++ b/src/opticalcontroller/tools.py @@ -0,0 +1,175 @@ +import numpy as np +from variables import * +import json + + +def common_slots(a, b): + return list(np.intersect1d(a, b)) + + +def map_modulation_to_op(mod): + if mod == "DP-QPSK": + return 1 + if mod == "DP-16QAM": + return 7 + if mod == "DP-64QAM": + return 10 + + +def map_band_to_slot(band): + return int(band/12.5) + + +def map_rate_to_slot(rate): + if rate == 100: + mod = "DP-QPSK" + slots = 4 + op = map_modulation_to_op(mod) + return op, slots + if rate == 400: + mod = "DP-16QAM" + slots = 8 + op = map_modulation_to_op(mod) + return op, slots + if rate == 1000: + mod = "DP-64QAM" + slots = 18 + op = map_modulation_to_op(mod) + return op, slots + else: + return 2, 5 + + +def consecutives(x, val): + res = [] + temp = [] + x.sort() + temp.append(x[0]) + y = 1 + for i in range(1, len(x)): + if x[i] == x[i - 1] + 1: + y += 1 + temp.append(x[i]) + else: + if y >= val: + res.extend(temp) + temp = [x[i]] + y = 1 + if i == len(x) - 1 and y >= val: + res.extend(temp) + return res + + +def combine(ls1, ls2): + temp = ls1 + for i in ls2: + if i not in ls1: + temp.append(i) + temp.sort() + return temp + + +def list_in_list(a, b): + # convert list A to numpy array + a_arr = np.array(a) + # convert list B to numpy array + b_arr = np.array(b) + + for i in range(len(b_arr)): + if np.array_equal(a_arr, b_arr[i:i + len(a_arr)]): + return True + return False + + +def reverse_link(link): + s, d = link.split('-') + r_link = "{}-{}".format(d, s) + return r_link + + +def get_slot_frequency(b, n): + if debug: + print(n) + if b == "c_slots": + return Fc + n * 12.5 + if b == "s_slots": + return Fs + n * 12.5 + if b == "l_slots": + return Fl + n * 12.5 + + +def freqency_converter(b, slots): + l = len(slots) + if debug: + print(slots) + if l % 2 == 0: + if debug: + print("pari {}".format(l)) + fx = get_slot_frequency(b, slots[int(l / 2)-1]) + if debug: + print(fx) + #GHz + # #f0 = fx + 6.25 + #MHz + f0 = int((fx + 6.25) * 1000) + else: + f0 = get_slot_frequency(b, slots[int((l + 1) / 2) - 1]) + #GHz + # #return f0, 12.5 * l + # MHz + return f0, int((12.5 * l) * 1000) + + +def readTopologyData(nodes, topology): + nodes_file = open(nodes, 'r') + topo_file = open(topology, 'r') + nodes = json.load(nodes_file) + topo = json.load(topo_file) + print(topo) + nodes_file.close() + topo_file.close() + return nodes, topo + + +def reverse_links(links): + temp_links = links.copy() + temp_links.reverse() + result = [] + for link in temp_links: + [a, b] = link.split("-") + result.append("{}-{}".format(b, a)) + return result + +def get_links_from_node(topology, node): + result = {} + for link in topology["links"]: + if "{}-".format(node) in link["optical_link"]["name"]: + result[link["optical_link"]["name"]] = link + return result + +def get_links_to_node(topology, node): + result = {} + for link in topology["links"]: + if "-{}".format(node) in link["optical_link"]["name"]: + result[link["optical_link"]["name"]] = link + return result + + +def slot_selection(c, l, s, n_slots, Nc, Nl, Ns): + # First Fit + if isinstance(n_slots, int): + slot_c = n_slots + slot_l = n_slots + slot_s = n_slots + else: + slot_c = Nc + slot_l = Nl + slot_s = Ns + if len(c) >= slot_c: + return "c_slots", c[0: slot_c] + elif len(l) >= slot_l: + return "l_slots", l[0: slot_l] + elif len(l) >= slot_s: + return "s_slots", s[0: slot_s] + else: + return None, None diff --git a/src/opticalcontroller/variables.py b/src/opticalcontroller/variables.py new file mode 100644 index 000000000..32fe4bd8d --- /dev/null +++ b/src/opticalcontroller/variables.py @@ -0,0 +1,18 @@ +debug = 1 + +Fl = 184800 +Fc = 192000 +Fs = 196200 + +Nl = 550 +Nc = 320 +#Nc = 10 +Ns = 720 + +nodes_json = 'json_files/nodes.json' +topology_json = 'json_files/tfs.json' #LAST +#topology_json = 'json_files/optical_TFSworking.json' #LAST +#topology_json = 'json_files/optical_topoTFS.json' +#topology_json = 'json_files/topo_2_links.json' + +testing = 1 -- GitLab From ed6e4f97fcba0203456b1e928cfe5af3676fcb2f Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 20 Feb 2024 16:21:20 +0000 Subject: [PATCH 2/3] Optical Controller component: - Pre-merge cleanup --- src/opticalcontroller/OpticalController.py | 14 ++++++++++++++ src/opticalcontroller/RSA.py | 14 ++++++++++++++ src/opticalcontroller/__init__.py | 13 +++++++++++++ src/opticalcontroller/dijsktra.py | 16 +++++++++++++++- src/opticalcontroller/requirements.in | 14 ++++++++++++++ src/opticalcontroller/tools.py | 14 ++++++++++++++ src/opticalcontroller/variables.py | 14 ++++++++++++++ 7 files changed, 98 insertions(+), 1 deletion(-) diff --git a/src/opticalcontroller/OpticalController.py b/src/opticalcontroller/OpticalController.py index 1acb67481..e8e0e2164 100644 --- a/src/opticalcontroller/OpticalController.py +++ b/src/opticalcontroller/OpticalController.py @@ -1,3 +1,17 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from flask import Flask from flask import render_template from flask_restplus import Resource, Api diff --git a/src/opticalcontroller/RSA.py b/src/opticalcontroller/RSA.py index 47ddbe71c..acf080d7f 100644 --- a/src/opticalcontroller/RSA.py +++ b/src/opticalcontroller/RSA.py @@ -1,3 +1,17 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import dijsktra from tools import * from variables import * diff --git a/src/opticalcontroller/__init__.py b/src/opticalcontroller/__init__.py index e69de29bb..38d04994f 100644 --- a/src/opticalcontroller/__init__.py +++ b/src/opticalcontroller/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/src/opticalcontroller/dijsktra.py b/src/opticalcontroller/dijsktra.py index 5be78c624..7ddfa325a 100644 --- a/src/opticalcontroller/dijsktra.py +++ b/src/opticalcontroller/dijsktra.py @@ -1,3 +1,17 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import sys class Vertex: @@ -219,4 +233,4 @@ if __name__ == '__main__': print ('The shortest path : %s' %(path[::-1]))""" p = shortest_path(g, g.get_vertex('a'), g.get_vertex('e')) - print(p) \ No newline at end of file + print(p) diff --git a/src/opticalcontroller/requirements.in b/src/opticalcontroller/requirements.in index e4b8abe1b..fefe604bc 100644 --- a/src/opticalcontroller/requirements.in +++ b/src/opticalcontroller/requirements.in @@ -1,3 +1,17 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + Flask==1.1.2 flask-restplus==0.13.0 itsdangerous==1.1.0 diff --git a/src/opticalcontroller/tools.py b/src/opticalcontroller/tools.py index d91240d45..3b3223d81 100644 --- a/src/opticalcontroller/tools.py +++ b/src/opticalcontroller/tools.py @@ -1,3 +1,17 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import numpy as np from variables import * import json diff --git a/src/opticalcontroller/variables.py b/src/opticalcontroller/variables.py index 32fe4bd8d..cbb65200f 100644 --- a/src/opticalcontroller/variables.py +++ b/src/opticalcontroller/variables.py @@ -1,3 +1,17 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + debug = 1 Fl = 184800 -- GitLab From ff3fb583fc9828ec8986249a3ce57a5e6aebff0f Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 20 Feb 2024 16:29:42 +0000 Subject: [PATCH 3/3] Optical Controller component: - Pre-merge cleanup --- src/opticalcontroller/dijsktra.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/opticalcontroller/dijsktra.py b/src/opticalcontroller/dijsktra.py index 7ddfa325a..a86d1d93d 100644 --- a/src/opticalcontroller/dijsktra.py +++ b/src/opticalcontroller/dijsktra.py @@ -12,6 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +# TODO: migrate to NetworkX: +# https://networkx.org/documentation/stable/index.html +# https://networkx.org/documentation/stable/reference/algorithms/shortest_paths.html + import sys class Vertex: -- GitLab